using System.ComponentModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; namespace BeWo.Controls { public class MaskedTextBox : TextBox { /// /// Dependency property to store the mask to apply to the textbox /// public static readonly DependencyProperty MaskProperty = DependencyProperty.Register("Mask", typeof(string), typeof(MaskedTextBox), new UIPropertyMetadata(null, MaskChanged)); // callback for when the Mask property is changed /// /// Static Constructor /// static MaskedTextBox() { // override the meta data for the Text Proeprty of the textbox FrameworkPropertyMetadata metaData = new FrameworkPropertyMetadata(); metaData.CoerceValueCallback = ForceText; TextProperty.OverrideMetadata(typeof(MaskedTextBox), metaData); } // force the text of the control to use the mask /// /// Default constructor /// public MaskedTextBox() { // cancel the paste and cut command this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Paste, null, CancelCommand)); this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Cut, null, CancelCommand)); } /// /// Gets or sets the mask to apply to the textbox /// public string Mask { get { return (string)this.GetValue(MaskProperty); } set { this.SetValue(MaskProperty, value); } } /// /// Gets the MaskTextProvider for the specified Mask /// public MaskedTextProvider MaskProvider { get { MaskedTextProvider maskProvider = null; if (this.Mask != null) { maskProvider = new MaskedTextProvider(this.Mask); maskProvider.Set(this.Text); } return maskProvider; } } // cancel the command /// /// override the key down to handle delete of a character /// /// Arguments for the event protected override void OnPreviewKeyDown(KeyEventArgs e) { base.OnPreviewKeyDown(e); MaskedTextProvider provider = this.MaskProvider; int position = this.SelectionStart; if (e.Key == Key.Delete && position < this.Text.Length) { // handle the delete key if (provider.RemoveAt(position)) { this.RefreshText(provider, position); } e.Handled = true; } else if (e.Key == Key.Space) { if (provider.InsertAt(" ", position)) { this.RefreshText(provider, position); } e.Handled = true; } else if (e.Key == Key.Back) { // handle the back space if (position > 0) { position--; if (provider.RemoveAt(position)) { this.RefreshText(provider, position); } } e.Handled = true; } } /// /// override this method to replace the characters enetered with the mask /// /// Arguments for event protected override void OnPreviewTextInput(TextCompositionEventArgs e) { int position = this.SelectionStart; MaskedTextProvider provider = this.MaskProvider; if (position < this.Text.Length) { position = this.GetNextCharacterPosition(position); if (Keyboard.IsKeyToggled(Key.Insert)) { if (provider.Replace(e.Text, position)) { position++; } } else { if (provider.InsertAt(e.Text, position)) { position++; } } position = this.GetNextCharacterPosition(position); } this.RefreshText(provider, position); e.Handled = true; base.OnPreviewTextInput(e); } private static void CancelCommand(object sender, CanExecuteRoutedEventArgs e) { e.CanExecute = false; e.Handled = true; } private static object ForceText(DependencyObject sender, object value) { MaskedTextBox textBox = (MaskedTextBox)sender; if (textBox.Mask != null) { MaskedTextProvider provider = new MaskedTextProvider(textBox.Mask); provider.Set((string)value); return provider.ToDisplayString(); } else { return value; } } private static void MaskChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { // make sure to update the text if the mask changes MaskedTextBox textBox = (MaskedTextBox)sender; textBox.RefreshText(textBox.MaskProvider, 0); } // refreshes the text of the textbox // gets the next position in the textbox to move private int GetNextCharacterPosition(int startPosition) { int position = this.MaskProvider.FindEditPositionFrom(startPosition, true); if (position == -1) { return startPosition; } else { return position; } } private void RefreshText(MaskedTextProvider provider, int position) { this.Text = provider.ToDisplayString(); this.SelectionStart = position; } } }