Простое решения будет делать это с помощью преобразователя:
public class SpaceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string newValue = "";
int cnt = 0;
foreach (char c in value.ToString())
{
if (cnt == 2)
{
newValue += " ";
cnt=0;
}
newValue += c;
cnt++;
}
return newValue;
}
public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
{
return value.Tostring().Replace(" ","");
}
}
EDIT: Для того, чтобы установить курсор я создал вложенное свойство, которое заботится о форматировании:
public class TextBoxFormatter
{
public static readonly DependencyProperty EnableFormattingProperty =
DependencyProperty.RegisterAttached("EnableFormatting", typeof(bool), typeof(TextBoxFormatter),
new PropertyMetadata(default(bool), PropertyChangedCallback));
private static void PropertyChangedCallback(DependencyObject dependencyObject,
DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
TextBox tb = dependencyObject as TextBox;
if (tb != null)
{
bool value = (bool)dependencyPropertyChangedEventArgs.NewValue;
tb.TextChanged -= TBTextChanged;
if (value)
{
Format(tb, true);
tb.TextChanged += TBTextChanged;
}
}
}
public static void SetEnableFormatting(TextBox element, bool value)
{
element.SetValue(EnableFormattingProperty, value);
}
public static bool GetEnableFormatting(TextBox element)
{
return (bool) element.GetValue(EnableFormattingProperty);
}
private static void TBTextChanged(object sender, TextChangedEventArgs e)
{
Format(sender as TextBox);
}
private static void Format(TextBox tb, bool init = false)
{
if (tb != null)
{
int ci = tb.CaretIndex;
string newValue = "";
int cnt = 0;
foreach (char c in tb.Text)
{
if (c != ' ')
{
if (cnt > 0 && ShouldFormat(cnt))
{
newValue += " ";
if (ci > cnt && init)
ci++;
}
cnt++;
newValue += c;
}
}
tb.Text = newValue;
SetCaret(tb, ci);
}
}
private static void SetCaret(TextBox tb, int oldCaret)
{
if (oldCaret <= 0 || oldCaret >= tb.Text.Length)
return;
if (tb.Text[oldCaret-1] != ' ' && tb.Text[oldCaret] != ' ')
tb.CaretIndex += oldCaret;
else
tb.CaretIndex = oldCaret+1;
}
private static bool ShouldFormat(int index)
{
return index%2 == 0;
}
}
Как использовать:
<TextBox ns:TextBoxFormatter.EnableFormatting="True"></TextBox>
Хорошая идея, но она не соответствует критериям «.. пока пользователь редактирует». Конвертер вызывается только тогда, когда пользователь покидает текстовое поле. –
@ RolandBär Нет, если вы установите свойство UpdateSourceTrigger = PropertyChanged в вашей привязке он обновляет значение сразу, когда пользователь набирает. –
Да, это работает, но возникает еще одна проблема: при вводе третьего символа пробел вставляется, но курсор остается в позиции. Поэтому ввод 1-2-3-4 приводит к " 12 43 ", возникающие для каждого вставленного пространства ... Любая идея, как это решить? –