I originally wrote this post in 2009 as part of an introduction to behaviors for Expression Blend. Despite “rebooting” my site, it continues to be one of the most referenced articles so I’m resurrecting it for posterity.
ehaviors, which implement a mechanism for wrapping control functionality into reusable blocks, were introduced in Expression Blend 3. They're not a new concept; packaging control event handlers in a separate, reusable class has been possible since .Net was first introduced. What is new is the seamless integration with a Visual Designer (in this case, Expression Blend). Behaviors enable a truly great design-time experience when applying custom functionality to UI controls. Something that, until now, has required an unwieldy amount of custom code.
The TextboxEditMask behavior, as you might guess from the name, adds edit mask functionality to a textbox. It comes in both Silverlight and a WPF flavors. You can:
- Download the source code as a Visual Studio 2008 project and compile it yourself, or
- You can just Trust the Monk with the pre-compiled DLLs.
Behaviors: the Quick Run Down
This isn't a tutorial on behaviors, so I won't delve too deeply into the details of their usage, but at the time of this writing they really are a relatively new feature on the Expression Blend landscape, so a quick step through of their use is in order:
Step two: Drag the behavior from your "Assets" pane and drop it on to a control (in this case, a TextBox control). This creates an instance of the behavior and applies it to the control.
Finally: Select the behavior you've just applied from the "Objects and Timeline" pane:
Properties of the TextboxEditMask
After selecting an instance of the TextboxEditMask behavior, three custom properties will show in the "Properties" pane:
The first, EditMask, holds the pattern to be enforced. This mask should conform to the CodingMonk Edit Mask notation (version 1.1). The notation is relatively easy to learn, especially if you've had experience with more exhaustive notations such as Regular Expressions.
The second parameter, MatchCaseToMask, is a checkbox. This is off by default, rendering the edit mask case-insensitive. This means when a letter appears in an edit mask, either the upper or lowercase version of that letter is allowed. If the pattern calls for the capitol letter "A", the lowercase "a" would also be accepted and displayed as lowercase. Checking this box causes the text to conform to the case of the pattern. In this example, the lowercase "a" would still be allowed as input, but it would be rendered in uppercase in the textbox.
The final parameter, PadEmptyBehavior, is a drop down list with the two possible options:
These effect what is displayed when backspaces and deletes occur. Since edit masks are typically fixed width, the backspace and delete keys have the effect of replacing the next and previous character. InferCharacter, the default, makes a decision based on allowable characters in the pattern. The alternative, UseUnderscore, simply enforces an underscore for character positions not yet filled in.
Although behaviors are currently an Expression Blend feature, TextboxEditMask allows you to set its properties and call methods from within your source code as well. To do this, you must first get a reference to the behavior. A static dictionary is provided at the class level, which allows you to lookup instances of the TextboxEditMask by the control they are applied to. For example:
TextboxEditMask phonemask = TextboxEditMask.Instances[tbPhoneNumber];
So changing the behavior's properties at runtime is straightforward:
phonemask.PadEmptyBehavior = TextboxEditMask.PadEmptyCharacter.UseUnderscore;
The TextboxEditMask behavior offers an additional helper property, MaskCompliantEmptyText, for your code. This property provides a string of text that effectively represents an empty value which is compliant to the current EditMask property. This is helpful when clearing a field to nothing:
Which, following the previous lines of code, would set the textbox display to:
It's worth pointing out that the edit mask doesn't try to outthink you (the developer), and it doesn't try to undo what you assign in code. So if your edit mask defines a pattern meant for a time in 12 hour format:
[ 01]#[*[ 0]#|1[0-2]]:[0-5]# [AP]M
But you pre-populate it with:
malum in se
Don't be surprised if users find your app unintuitive.