All the controls missing in WPF. Over 1 million downloads.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

255 lines
8.4 KiB

using System;
using System.Windows.Controls;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;
using Microsoft.Windows.Controls.Primitives;
namespace Microsoft.Windows.Controls
{
public class MaskedTextBox : InputBase
{
#region Properties
protected MaskedTextProvider MaskProvider { get; set; }
private TextBox TextBox { get; set; }
#region IncludePrompt
public static readonly DependencyProperty IncludePromptProperty = DependencyProperty.Register("IncludePrompt", typeof(bool), typeof(MaskedTextBox), new UIPropertyMetadata(false, OnIncludePromptPropertyChanged));
public bool IncludePrompt
{
get { return (bool)GetValue(IncludePromptProperty); }
set { SetValue(IncludePromptProperty, value); }
}
private static void OnIncludePromptPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if (maskedTextBox != null)
maskedTextBox.OnIncludePromptChanged((bool)e.OldValue, (bool)e.NewValue);
}
protected virtual void OnIncludePromptChanged(bool oldValue, bool newValue)
{
ResolveMaskProvider(Mask);
}
#endregion //IncludePrompt
#region IncludeLiterals
public static readonly DependencyProperty IncludeLiteralsProperty = DependencyProperty.Register("IncludeLiterals", typeof(bool), typeof(MaskedTextBox), new UIPropertyMetadata(true, OnIncludeLiteralsPropertyChanged));
public bool IncludeLiterals
{
get { return (bool)GetValue(IncludeLiteralsProperty); }
set { SetValue(IncludeLiteralsProperty, value); }
}
private static void OnIncludeLiteralsPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if (maskedTextBox != null)
maskedTextBox.OnIncludeLiteralsChanged((bool)e.OldValue, (bool)e.NewValue);
}
protected virtual void OnIncludeLiteralsChanged(bool oldValue, bool newValue)
{
ResolveMaskProvider(Mask);
}
#endregion //IncludeLiterals
#region Mask
public static readonly DependencyProperty MaskProperty = DependencyProperty.Register("Mask", typeof(string), typeof(MaskedTextBox), new UIPropertyMetadata(default(String), OnMaskPropertyChanged));
public string Mask
{
get { return (string)GetValue(MaskProperty); }
set { SetValue(MaskProperty, value); }
}
private static void OnMaskPropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
{
MaskedTextBox maskedTextBox = o as MaskedTextBox;
if (maskedTextBox != null)
maskedTextBox.OnMaskChanged((string)e.OldValue, (string)e.NewValue);
}
protected virtual void OnMaskChanged(string oldValue, string newValue)
{
ResolveMaskProvider(newValue);
UpdateText(MaskProvider, 0);
}
#endregion //Mask
#endregion //Properties
#region Constructors
static MaskedTextBox()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MaskedTextBox), new FrameworkPropertyMetadata(typeof(MaskedTextBox)));
}
#endregion //Constructors
#region Overrides
public override void OnApplyTemplate()
{
TextBox = GetTemplateChild("TextBox") as TextBox;
TextBox.PreviewTextInput += TextBox_PreviewTextInput;
TextBox.PreviewKeyDown += TextBox_PreviewKeyDown;
}
protected override object ConvertTextToValue(string text)
{
object convertedValue = null;
Type dataType = ValueType;
string valueToConvert = MaskProvider.ToString();
if (valueToConvert.GetType() == dataType || dataType.IsInstanceOfType(valueToConvert))
{
convertedValue = valueToConvert;
}
else if (String.IsNullOrWhiteSpace(valueToConvert))
{
convertedValue = Activator.CreateInstance(dataType);
}
else if (null == convertedValue && valueToConvert is IConvertible)
{
convertedValue = Convert.ChangeType(valueToConvert, dataType);
}
return convertedValue;
}
protected override string ConvertValueToText(object value)
{
if (value == null)
value = string.Empty;
MaskProvider.Set(value.ToString());
return MaskProvider.ToDisplayString();
}
#endregion
#region Event Handlers
void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
//if the text is readonly do not add the text
if (TextBox.IsReadOnly)
{
e.Handled = true;
return;
}
int position = TextBox.SelectionStart;
MaskedTextProvider provider = MaskProvider;
if (position < TextBox.Text.Length)
{
position = GetNextCharacterPosition(position);
if (Keyboard.IsKeyToggled(Key.Insert))
{
if (provider.Replace(e.Text, position))
position++;
}
else
{
if (provider.InsertAt(e.Text, position))
position++;
}
position = GetNextCharacterPosition(position);
}
UpdateText(provider, position);
e.Handled = true;
base.OnPreviewTextInput(e);
}
void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
base.OnPreviewKeyDown(e);
MaskedTextProvider provider = MaskProvider;
int position = TextBox.SelectionStart;
int selectionlength = TextBox.SelectionLength;
// If no selection use the start position else use end position
int endposition = (selectionlength == 0) ? position : position + selectionlength - 1;
if (e.Key == Key.Delete && position < TextBox.Text.Length)//handle the delete key
{
if (provider.RemoveAt(position, endposition))
UpdateText(provider, position);
e.Handled = true;
}
else if (e.Key == Key.Space)
{
if (provider.InsertAt(" ", position))
UpdateText(provider, position);
e.Handled = true;
}
else if (e.Key == Key.Back)//handle the back space
{
if ((position > 0) && (selectionlength == 0))
{
position--;
if (provider.RemoveAt(position))
UpdateText(provider, position);
}
if (selectionlength != 0)
{
if (provider.RemoveAt(position, endposition))
{
if (position > 0)
position--;
UpdateText(provider, position);
}
}
e.Handled = true;
}
}
#endregion //Event Handlers
#region Methods
private void UpdateText(MaskedTextProvider provider, int position)
{
Text = provider.ToDisplayString();
if (TextBox != null)
TextBox.SelectionStart = position;
}
private int GetNextCharacterPosition(int startPosition)
{
int position = MaskProvider.FindEditPositionFrom(startPosition, true);
return position == -1 ? startPosition : position;
}
private void ResolveMaskProvider(string mask)
{
MaskProvider = new MaskedTextProvider(mask)
{
IncludePrompt = this.IncludePrompt,
IncludeLiterals = this.IncludeLiterals
};
}
#endregion //Methods
}
}