206 lines
6.5 KiB
C#
206 lines
6.5 KiB
C#
using System.ComponentModel;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
|
|
namespace BeWo.Controls
|
|
{
|
|
public class MaskedTextBox : TextBox
|
|
{
|
|
/// <summary>
|
|
/// Dependency property to store the mask to apply to the textbox
|
|
/// </summary>
|
|
public static readonly DependencyProperty MaskProperty = DependencyProperty.Register("Mask", typeof(string), typeof(MaskedTextBox), new UIPropertyMetadata(null, MaskChanged));
|
|
|
|
// callback for when the Mask property is changed
|
|
|
|
/// <summary>
|
|
/// Static Constructor
|
|
/// </summary>
|
|
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
|
|
|
|
///<summary>
|
|
/// Default constructor
|
|
///</summary>
|
|
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));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the mask to apply to the textbox
|
|
/// </summary>
|
|
public string Mask
|
|
{
|
|
get
|
|
{
|
|
return (string)this.GetValue(MaskProperty);
|
|
}
|
|
|
|
set
|
|
{
|
|
this.SetValue(MaskProperty, value);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the MaskTextProvider for the specified Mask
|
|
/// </summary>
|
|
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
|
|
|
|
/// <summary>
|
|
/// override the key down to handle delete of a character
|
|
/// </summary>
|
|
/// <param name="e">Arguments for the event</param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// override this method to replace the characters enetered with the mask
|
|
/// </summary>
|
|
/// <param name="e">Arguments for event</param>
|
|
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;
|
|
}
|
|
}
|
|
} |