Enforce Text Case with Custom Controls

Introduction

This article shall describe the construction of three custom controls; each is used to format its text content to be either all upper case, all lower case, title case, or normal (as typed) case regardless of the format of the input. Such controls may be useful if it is necessary to load the control's text from a source in which the values are in the wrong case; for example, if one were to load a ListBox from a column in a database where all of the values were stored as all upper case strings but the desire was to display the text using title case, the Case List control contained in the sample project will make the conversion once the values are loaded into its list.

Image1.jpg

Figure 1:  The Case Controls in Use.
 

Getting Started

The Case Controls solution contains two projects. The first project is called "CaseControls" and it contains three extended controls (the RichTextBox, the ListBox, and the ComboBox). Each of the controls was extended such that the modified version offered the option of formatting the text contained is the control into one of four options (Upper Case, Lower Case, Normal Case, and Title Case). The second project is called "TestCaseControl" and it is provided to demonstrate use of the controls in a Win Forms application.  

Image2.jpg

Figure 2:  Solution Explorer with Both Projects Visible.
 

The Case Controls Project

Code:  Case Text

The CaseText control is an extended version of the RichTextBox control; this control was extended such that text sent to the control or keyed directly into it is immediately formatted into one of the four available options (Upper Case, Lower Case, Normal Case, or Title Case). In use, the developer may drop the control onto a form and set a single property "TextCase" that is used by the control to determine how to format the text.

The control is built in a single class entitled "CaseText". The class begins with the following imports, namespace, and class declarations: 

using System;

using System.Collections;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using System.Globalization;

using System.Threading; 

 

namespace CaseControls

{

 

    /// <summary>

    /// Extend the RichTextBox control

    /// </summary>

    public class CaseText : RichTextBox

    { 

The class is declared to inherit from the RichTextBox control. By inheriting from the RichTextBox control, all of the functionality of that control is included. After declaring the class, the next section of code is used to declare an enumeration defining the case mode options, a private member variable used to hold the currently selected text case mode, and a public property used to set or retrieve the selected case mode:

/// <summary>

/// Enumeration of case type options

/// </summary>

public enum CaseType

{

    Normal,

    Title,

    Upper,

    Lower

} 

 

/// <summary>

/// Set the current case type for the control;

/// default to normal case

/// </summary>

private CaseType mCaseType = CaseType.Normal; 

 

/// <summary>

/// property used to maintain current case type

/// </summary>

public CaseType TextCase

{

    get

    {

        return mCaseType;

    }

    set

    {

        mCaseType = value;

        UpdateTextCase();

    }

}  

The next block of code contains the default constructor and the component initialization code; since this control is intended to serve as either a textbox or a richtextbox, the control's constructor contains a bit of code to make the control look more like a standard textbox control when it is created (the multi-line property is set to false and the height is set to 20). The initialize component method also includes the addition of a text changed event handler: 

/// <summary>

/// Default Constructor

/// </summary>

public CaseText()

{

    InitializeComponent();

    this.Text = string.Empty;

    this.Multiline = false;

    this.Height = 20;

} 

 

/// <summary>

/// Initialization/Event Handlers

/// </summary>

private void InitializeComponent()

{

    this.SuspendLayout();

    //

    // CaseText

    //

    this.TextChanged += new System.EventHandler(this.CaseText_TextChanged);

    this.ResumeLayout(false);

} 

The last bit of code required by the control is the text changed event handler which is used merely to call a method used to update the case of the text based upon the selected case mode property. Since this method is called whenever text changed event fires, the textbox will update the case as the user types. When the UpdateTextCase method is called, the method stores the text currently contained in the control and it stores the position of the insert cursor. The copy of the text placed in the string varible is operated on within the method and then is used to replace the text contained in the control. The position of the insert is stored so that the cursor may be restored to its original position after the text has been replaced. This supports edits made to sections of the string other than the end or beginning of the string. 

/// <summary>

/// Call the Update Text Case function each time

/// the text changes

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void CaseText_TextChanged(object sender, EventArgs e)

{

    UpdateTextCase();

} 

 

/// <summary>

/// Depending upon the Case Type selected,

/// process the textbox accordingly

/// </summary>

private void UpdateTextCase()

{

    string sControlText = this.Text;

    int cursorPosition = this.SelectionStart;

 

    switch (this.TextCase)

    {

        case CaseType.Lower:

            // convert to all lower case

            this.Text = this.Text.ToLower();

            break;

        case CaseType.Normal:

            // do nothing, leave as entered

            break;

        case CaseType.Title:

            // convert to title case

            string sTemp = this.Text.ToLower();

            CultureInfo ci = Thread.CurrentThread.CurrentCulture;

            TextInfo ti = ci.TextInfo;

            this.Text = ti.ToTitleCase(sTemp);

            break;

        case CaseType.Upper:

            // convert to all upper case

            this.Text = this.Text.ToUpper();

            break;

        default:

            break;

    }

    // move to the corrent position in the string

    this.SelectionStart = cursorPosition;

}

The code used in the CaseList and CaseCombo controls is very similar and is all included in the download; for that reason I won't describe it here in this document. The only major difference between the code used in those controls is that the Update Text methods are made public in the list controls so that the user may evoke the method whenever the list is created or changed.  Whenever the user evokes the method, the update method will loop through the text in the collection and update the case of each list item. 

Code:  Test Case Control

This project is used to test the custom controls. The project contains a single Windows form. The form contains four of each type of custom control, each of which is intended to demonstrate one of the case mode options. 

The form class begins with the default imports and class declaration:

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

 

namespace TestCaseControl

{

    public partial class Form1 : Form

    { 

In the form constructor, the list type controls are all populated manually using strings formatting contrary to what is desired for display. For example, the if the custom listbox control is set to display upper case text, the text submitted to the control's list is passed in using lower case or mixed case strings. After each list is loaded, the controls update text case method is evoked to reformat the case used in the list items: 

public Form1()

{

    InitializeComponent();

 

    // C O M B O  B O X  E X A M P L E

    //

    // load an Upper Case list with these items

    caseCombo1.Items.Add("popeye");

    caseCombo1.Items.Add("olive oil");

    caseCombo1.Items.Add("brutus");

    caseCombo1.Items.Add("whimpy");

    caseCombo1.Items.Add("sweet pea");   
    
// update the case of these list items

    caseCombo1.UpdateListTextCase(); 

 

    // load a Lower Case list with these items

    caseCombo2.Items.Add("CHOCOLATE CREAM");

    caseCombo2.Items.Add("Rasberry Truffle");

    caseCombo2.Items.Add("PINEAPPLE Sling");

    caseCombo2.Items.Add("COCONUT HEaRt");

    caseCombo2.Items.Add("VANILLA ICE Cream");

    // update the case of these list items

    caseCombo2.UpdateListTextCase(); 

 

    // load a Normal Case list with these items

    caseCombo3.Items.Add("George S. Patton");

    caseCombo3.Items.Add("Mikhail Miloradovich");

    caseCombo3.Items.Add("Bernard Montgomery");

    caseCombo3.Items.Add("Carl von Clausewitz");

    caseCombo3.Items.Add("Sun Tzu");

    // update the case of these list items

    caseCombo3.UpdateListTextCase(); 

 

    // load a Title Case list with these items

    caseCombo4.Items.Add("john lennon");

    caseCombo4.Items.Add("paul mc cartney");

    caseCombo4.Items.Add("ringo starr");

    caseCombo4.Items.Add("george harrison");

    caseCombo4.Items.Add("peter best");

    // update the case of these list items

    caseCombo4.UpdateListTextCase(); 

 

    // L I S T  B O X  E X A M P L E

    //

    // load an Upper Case list with these items

    caseList1.Items.Add("popeye");

    caseList1.Items.Add("olive oil");

    caseList1.Items.Add("brutus");

    caseList1.Items.Add("whimpy");

    caseList1.Items.Add("sweet pea");

    // update the case of these list items

    caseList1.UpdateListTextCase(); 

 

    // load a Lower Case list with these items

    caseList2.Items.Add("CHOCOLATE CREAM");

    caseList2.Items.Add("Rasberry Truffle");

    caseList2.Items.Add("PINEAPPLE Sling");

    caseList2.Items.Add("COCONUT HEaRt");

    caseList2.Items.Add("VANILLA ICE Cream");

    // update the case of these list items

    caseList2.UpdateListTextCase(); 

 

    // load a Normal Case list with these items

    caseList3.Items.Add("George Patton");

    caseList3.Items.Add("Mikhail Miloradovich");

    caseList3.Items.Add("Bernard Montgomery");

    caseList3.Items.Add("Carl von Clausewitz");

    caseList3.Items.Add("Sun Tzu");

    // update the case of these list items

    caseList3.UpdateListTextCase(); 

 

    // load a Title Case list with these items

    caseList4.Items.Add("john lennon");

    caseList4.Items.Add("paul mc cartney");

    caseList4.Items.Add("ringo starr");

    caseList4.Items.Add("george harrison");

    caseList4.Items.Add("peter best");

    // update the case of these list items

    caseList4.UpdateListTextCase(); 

} 

The only other code in the form class are a set button event handlers that will pass an improperly formatted string to each of the four custom case text controls: 

/// <summary>

/// Button event handlers used to send

/// formatted strings to each of the

/// CaseText controls on the page.  Each

/// example is set to a different type

/// of case (Upper, Lower, Normal, and Title)

/// </summary>

/// <param name="sender"></param>

/// <param name="e"></param>

private void btnToUpper_Click(object sender, EventArgs e)

{

    caseText1.Text = lblToUpperCase.Text;

}

 

private void btnToLower_Click(object sender, EventArgs e)

{

    caseText2.Text = lblToLowerCase.Text;

}

 

private void btnToNormal_Click(object sender, EventArgs e)

{

    caseText3.Text = lblToNormalCase.Text;

}

 

private void btnToTitle_Click(object sender, EventArgs e)

{

    caseText4.Text = lblToTitleCase.Text;

} 

Summary.

This article was intended to demonstrate an approach to building a set of custom controls that could be used to reformat the case of the text or list item text; the purpose of such a control would be to allow improperly formatted text obtained from an external source to be properly displayed in the context of a Windows application without the need to modify the source of text.  Such a control may be useful if one is, for example, attempting to display data obtained from a database that is not stored in the proper format (e.g., the column contains all upper case strings but the desire is to display it as title case strings or all lower case string).

X

Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now