Skip to content

Instantly share code, notes, and snippets.

@mvacha
Created May 17, 2016 14:02
Show Gist options
  • Save mvacha/79255a156347b1e4f3cc520dc93fd84a to your computer and use it in GitHub Desktop.
Save mvacha/79255a156347b1e4f3cc520dc93fd84a to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace WpfTest
{
public enum MaskType
{
None = 0,
Isic = 1,
}
public partial class TextBoxExt
{
#region Dependency Property
public static readonly DependencyProperty MaskProperty = DependencyProperty.RegisterAttached("Mask",
typeof(MaskType), typeof(TextBoxExt), new FrameworkPropertyMetadata(MaskChangedCallback));
public static MaskType GetMask(DependencyObject obj)
{
return (MaskType)obj.GetValue(MaskProperty);
}
public static void SetMask(DependencyObject obj, MaskType value)
{
obj.SetValue(MaskProperty, value);
}
private static void MaskChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var oldVal = e.OldValue as TextBox;
if (oldVal != null)
{
oldVal.PreviewTextInput -= TextBox_PreviewTextInput;
oldVal.PreviewKeyDown -= TextBox_PreviewKeyDown;
DataObject.RemovePastingHandler(oldVal, (DataObjectPastingEventHandler)TextBoxPastingEventHandler);
}
var textBox = d as TextBox;
if (textBox == null)
return;
if ((MaskType)e.NewValue != MaskType.None)
{
textBox.PreviewTextInput += TextBox_PreviewTextInput;
textBox.PreviewKeyDown += TextBox_PreviewKeyDown;
DataObject.AddPastingHandler(textBox, (DataObjectPastingEventHandler)TextBoxPastingEventHandler);
}
}
#endregion
private static void TextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
var textBox = sender as TextBox;
if (textBox == null) return;
var caret = textBox.CaretIndex;
var oldText = textBox.Text;
if (e.Key == Key.Back)
{
if (oldText.Length == 0 || caret == 0)
{
e.Handled = true;
textBox.Text = oldText;
return;
}
if (textBox.SelectionLength > 0)
{
oldText = oldText.Remove(textBox.SelectionStart, textBox.SelectionLength);
caret = textBox.SelectionStart;
textBox.Text = FormatValue(GetMask(textBox), oldText);
textBox.CaretIndex = FixCaretIndex(GetMask(textBox), caret, oldText, true, false);
e.Handled = true;
}
var newText = oldText.Remove(caret-1, 1);
caret -= 1;
if (newText.Any() && caret > 0 && newText[caret-1] == ' ')
{
newText = newText.Remove(caret - 1, 1);
caret -= 1;
}
textBox.Text = FormatValue(GetMask(textBox), newText);
textBox.CaretIndex = FixCaretIndex(GetMask(textBox), caret, newText, true, false);
e.Handled = true;
}
else if (e.Key == Key.Delete)
{
if (oldText.Length == 0 || oldText.Length == caret)
{
e.Handled = true;
textBox.Text = oldText;
return;
}
if (textBox.SelectionLength > 0)
{
oldText = oldText.Remove(textBox.SelectionStart, textBox.SelectionLength);
caret = textBox.SelectionStart;
textBox.Text = FormatValue(GetMask(textBox), oldText);
textBox.CaretIndex = FixCaretIndex(GetMask(textBox), caret, oldText, false, true);
e.Handled = true;
}
var newText = oldText.Remove(caret, 1);
if (caret < newText.Length && newText[caret] == ' ')
{
newText = newText.Remove(caret, 1);
}
textBox.Text = FormatValue(GetMask(textBox), newText);
textBox.CaretIndex = FixCaretIndex(GetMask(textBox), caret, newText, false, true);
e.Handled = true;
}
else if (e.Key == Key.Right)
{
caret += 1;
if (caret < textBox.Text.Length && textBox.Text[caret] == ' ')
{
caret += 1;
}
textBox.CaretIndex = caret;
e.Handled = true;
}
else if (e.Key == Key.Left)
{
caret = Math.Max( caret - 1, 0);
if (caret > 0 && textBox.Text[caret-1] == ' ')
{
caret -= 1;
}
textBox.CaretIndex = caret;
e.Handled = true;
}
else if (e.Key == Key.Space)
{
e.Handled = true;
}
}
private static void TextBoxPastingEventHandler(object sender, DataObjectPastingEventArgs e)
{
TextBox tb = (sender as TextBox);
var text = tb.Text;
var caret = tb.CaretIndex;
string clipboard = e.DataObject.GetData(typeof(string)) as string;
if (tb.SelectionLength != 0)
{
text = text.Remove(tb.SelectionStart, tb.SelectionLength);
caret = tb.SelectionStart;
}
text = text.Insert(caret, clipboard);
caret += clipboard.Length;
tb.Text = FormatValue(GetMask(tb), text);
tb.CaretIndex = tb.Text.Length;
e.CancelCommand();
e.Handled = true;
}
private static void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
var textbox = sender as TextBox;
if (textbox == null) return;
e.Handled = false;
var caretIndex = textbox.CaretIndex;
var text = textbox.Text;
if (textbox.SelectionLength != 0)
{
text = text.Remove(textbox.SelectionStart, textbox.SelectionLength);
}
var newText = FormatValue(GetMask(textbox), text.Insert(caretIndex, e.Text));
textbox.Text = newText;
caretIndex += 1;
textbox.CaretIndex = FixCaretIndex(GetMask(textbox), caretIndex, newText, true, false);
e.Handled = true;
}
private static int FixCaretIndex(MaskType mask, int caretIndex, string text, bool moveForward = true, bool moveBackward = true)
{
if (moveBackward && caretIndex < text.Length && text[caretIndex] == ' ')
{
caretIndex -= 1;
}
else if (moveForward && caretIndex < text.Length && caretIndex > 0 && text[caretIndex - 1] == ' ')
{
caretIndex += 1;
}
if (caretIndex >= text.Length)
{
caretIndex = text.Length;
}
return caretIndex;
}
private static string FormatValue(MaskType mask, string value)
{
if (mask != MaskType.Isic) return String.Empty;
var sbuilder = new StringBuilder();
var index = 0;
value = value.RemoveWhitespace().ToUpper();
if (value.Length > 11)
value = value.Substring(0, 11);
foreach (var ch in value)
{
if (ch != ' ' && (index == 1 || index == 4 || index == 7 || index == 10))
{
sbuilder.Append(' ');
}
sbuilder.Append(ch);
index++;
}
return sbuilder.ToString();
}
}
public static class Extensions
{
public static string RemoveWhitespace(this string input)
{
return new string(input.ToCharArray()
.Where(c => !Char.IsWhiteSpace(c))
.ToArray());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment