Haven't update my blog for long time.. too many things to handle these days
I noticed lots of people on the Silverlight forum are asking for some FREE MaskedTextBox for Silverlight, well, I know telerik do provide a control called RadMaskedTextBox and it's pretty good, But I want to say by using Behavior, you can create a MaskedTextBox from scratch as well, and it works pretty well
First what is Behavior? Behavior was a set of classes which was introduced by Blend in order to let UI designer to easily extend a control's ability.
to start, you need a reference to a Blend Assembly:
Microsoft.Expression.Interactivity.dll
and in XAML you need a namespace for this Assembly(normally we use i: for this namespace)
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
in project, we add a class "MastTextBoxBehavior.cs" which inhered from Behavior<TextBox> class(because we want to extend the functionality of element TextBox, so inside the generic <>, we'd better fill class TextBox)
public class MaskTextBoxBehavior : Behavior<TextBox> {...}
next, we have to define a DependencyProperty which could enable binding and animation
public static readonly DependencyProperty TrueTextProperty =
DependencyProperty.Register("TrueText", typeof(string),typeof(MaskTextBoxBehavior), null);
We define this DependencyProperty TrueTextProperty is because we have to let other UI element to access the true text value of the MaskedTextBox later.
Add a wrapper for this DependencyProperty
public string TrueText
{
get
{
return (string)GetValue(TrueTextProperty);
}
set
{
SetValue(TrueTextProperty, value);
}
}
Inside the OnAttached() method, add a handler for TextChanged event
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
TrueText = string.Empty;
}
void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
{
int index = AssociatedObject.SelectionStart;
string newString = AssociatedObject.Text.Substring(index - 1, 1);
if(TrueText.Length != AssociatedObject.Text.Length)
TrueText = TrueText.Insert(index - 1, newString);
AssociatedObject.Text = new string('*', AssociatedObject.Text.Length);
AssociatedObject.SelectionStart = index;
}
The AssociatedObject_TextChanged method is in charge of watching the text change and save the true value into the TrueText property, while keeping the TextBox.Text always “*”, so what the user see on the screen will always be “*”, but through TrueText property, the user can access the complete text values he just typed.
The Behavior<> class is done, let’s return to XAML, write a <TextBox….> element like this(remember to add <i:../> namespace as I mentioned at the beginning, <local: .. is a namespce which include the MaskTextBoxBehavior Behavior)
<TextBox MinWidth="200">
<i:Interaction.Behaviors>
<local:MaskTextBoxBehavior x:Name="mm"/>
</i:Interaction.Behaviors>
</TextBox>
Now the MaskTextBoxBehavior is attached to a TextBox element, you can add another <TextBlock> element and bind the Text property to the TrueText property of this Behavior for testing, like this:
<StackPanel VerticalAlignment="Top" HorizontalAlignment="Left">
<TextBox MinWidth="200">
<i:Interaction.Behaviors>
<local:MaskTextBoxBehavior x:Name="mm"/>
</i:Interaction.Behaviors>
</TextBox>
<TextBlock Text="{Binding TrueText, ElementName=mm}"/>
</StackPanel>
When you typing in the TextBox, what you will see will always be the “*”s, and in the same time the <TextBlock..> will show the actual values.
Now a MaskedTextBox is done, you don’t need to spend money buying the third party Component, just using a Behavior…
For the time issue, I didn’t make the method
void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
perfect, Currently the method only support adding a char, if you try to use Backspace to delete a cha in the TextBox, some error result will happen. While this’s not that difficult to make it perfect, just spend some time and do some careful testing is ok.
Enjoy the Silverlight