Introduction
Two controls are available in the CustomControls.dll. To use them, just add a reference to the DLL and you should get the two controls in your ToolBox (TextBoxEx
, StatusBarEx
).
TextBoxEx
is an extension of the standard TextBox
. It supports:
- Masking, (In mask character set, # = numbers, A = all capital letters, a = all small letters, $ = #,A,a, & = A,a)
- Regular expression validation (Custom and couple of built-in),
- Validation of letters only,
- Validation of numbers only,
- Validation for user defined characters/numbers,
- Built in
ErrorProvider
,
- Ability to use the ENTER key as TAB. (This becomes very handy for data entry operation type of applications.)
StatusBarEx
is an extension to the standard StatusBar
. It supports 4 types of panels.
- Date Panel,
- Time Panel,
- Smooth ProgressBar Panel,
- Pattern ProgressBar Panel (This is just a fancy one).
References
I have been looking for validation controls and came up with ValidText
control which is from Luis Alberto Ruiz Arauz (published in CodeProject). Because I wanted one in C#, I thought to convert the code to C# and to include some improvements (discussed below).
Ideas for the smooth progress bar was taken from the Microsoft KB article 323116.
Therefore, credits should go to these people as well, who share their knowledge with us. Similarly, if anybody uses this code and does any fixes/improvements, please let me know.
I have tested this code only on Windows 2000. But because it depends only on the .NET runtime, I think it will work well in other Operating Systems as well.
Code Description for TextBoxEx
TextBoxEx
control's MaskEdit functionality takes quite a different approach from Luis' VB.NET version. Therefore, I have managed to cut down lot of code, keep the same functionality and to fix some bugs.
KeyPress
event of the base TextBox
class has been overridden and all the validation for mask is done within the PerformMaskValidation
method. Within this method, for each mask character (#, A, a, %, $), valid data will be checked using IsValidInputForMask
. When TextBoxEx
control is working in Mask
mode, you cannot half fill the mask and leave the control. If you wish to leave it empty, you can do so by not entering ANY data. (But, if the IsRequired
property is set to true
, it will prompt for data when validating). That means, for a mask such as (###)-AA-aa:
- If
IsRequired=true
, then mask must be filled.
- If
IsRequired=false
, then mask can be left unfilled. But, you cannot half fill and try to leave the control.
TextBoxEx
in Mask
mode captures key combinations such as SHIFT-INSERT, CTRL-V (paste) and the context menu so that once the mask is set, you will not be able to accidentally clear it at runtime by setting any values to Text
property. To capture this keyboard input, I have overridden the ProcessCmdKey
event. If you try to over write the mask by assigning some value to Text
property, they will still be validated. For example, if the mask is (###)-AA, and if you assign txtBoxEx.Text="AB12CDEF"
, the Text
property will contain (12_)-__ only. (The mask is filled from left to right. Here, the input string has only 2 numeric, whereas the mask expects 3. Therefore, it accepts the 2 numeric and discard the others.) This way, it will avoid breaking the mask and throwing exceptions (which happens in other controls). Therefore, if you need to reset the mask at run time, you have to do this:
txtBoxEx.ValidationText="(###)-AA";
txtBoxEx.Text="123AB";
Additionally, if you want to validate all the TextBoxEx
controls at once (for example, to validate the entire form's TextBoxEx
controls just before adding the data into a database), you can use the public Validate()
method. In the sample application, this is shown in btnValidateAll_Click()
method.
private void btnValidateAll_Click(object sender, System.EventArgs e)
{
bool allValid=true;
allValid = RecursiveControlValidation(this);
if (allValid)
MessageBox.Show(this,"All controls contain valid data");
else
MessageBox.Show(this,
"Indicated controls contain invalid/incomplete data");
}
private bool RecursiveControlValidation(Control ctl)
{
bool isValid=true;
if (ctl.HasChildren)
{
foreach(Control c in ctl.Controls)
{
isValid &=RecursiveControlValidation(c);
}
}
if(ctl.GetType()==typeof(CustomControls.TextBoxEx))
{
if ( !((CustomControls.TextBoxEx)ctl).Validate() )
{
isValid =false;
}
}
return isValid;
}
The other useful option included here is the ability to move to the next control by pressing ENTER key. This may not sound critical, but I have come across a couple of projects where all data entry people insisted that they want to use ENTER key to move to the next textbox. (Actually, for data entry, this is easier than using the TAB.) In standard TextBox
, you will have to attach an event for this. But in TestBoxEx
, property UseEnterAsTab
set to true
and it will do the rest. The code that I use is:
protected override void OnKeyDown(System.Windows.Forms.KeyEventArgs e)
{
if (useEnterAsTab)
{
if (e.KeyCode == Keys.Enter)
{
SendKeys.Send("{Tab}");
e.Handled=true;
}
}
base.OnKeyDown(e);
}
Some other useful comments can be found in the code itself. If you are going to modify the code, you may find these comments useful.
Code Description for StatusBarEx
Because StatusBarEx
should support panels with progress bar, standard StatusBarPanel
has been extended to StatusBarPanelEx
. To be able to add StatusBarPanelEx
to StatusBarEx
at design time, a design time CollectionEditor
has been implemented. This code can be found in StatusBarPanelExCollectionEditor
class. Normal StatusBarPanelCollection
has been overridden by StatusBarPanelExCollection
class. This returns StatusBarPanelEx
types. The Panels
property in StatusBarEx
is defined to use the new StatusBarPanelExCollectionEditor
instead of the standard CollectionEditor
. (Otherwise, it will only add StatusBarPanel
types at design time.) What type editor is to be used has been designed using the following attributes:
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Editor(typeof(System.ComponentModel.Design.CollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
[Editor(typeof(StatusBarPanelExCollectionEditor),
typeof(System.Drawing.Design.UITypeEditor))]
public new StatusBarPanelExCollection Panels
{
}
ToDo
In TextBoxEx
, if somebody needs to keep the mask characters (A, a, $, &, #) as normal characters, then they should be escaped from the mask. I will be adding this feature shortly. Currently, if your mask is (###)-AA, it will get translated to (___)-__. But, what if you want to keep any of the above mask characters as normal characters? I will be using an escape sequence, so if you need, you can specify masks like (##\#)-A\A which will get translated to (__#)-_A.
Furthermore, I will be adding couple of more controls to this library that I have developed for my projects. Currently, a bit stuck in getting a custom designer to work. Does any of you guys know how to monitor the Component Tray in Visual Studio for component additions/deletions? If so, let me know.