Автоматически вставлять дефис после каждых 4 символов в TextBox

Я хочу реализовать кое-что, что, когда пользователь вводит 4 символа, к тексту должен быть добавлен дефис, а затем снова пользователь вводит 4 символа, а затем снова автоматически добавляется дефис в WPF.

Примечание

"Я хочу реализовать это поведение, когда пользователь вводит текст в текстовое поле (а не после того, как текстовое поле потеряло фокус), потому что это очень легко реализовать"

Используется модель MVVM, поэтому код диалогового окна должен быть пустым


person Yogesh    schedule 07.05.2013    source источник
comment
Попробуйте использовать MaskedTextBox: wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox   -  person Daniel Hilgarth    schedule 07.05.2013
comment
Дэниел Хилгарт, на самом деле я хочу использовать только обычное текстовое поле wpf   -  person Yogesh    schedule 07.05.2013
comment
Что является причиной этого?   -  person Daniel Hilgarth    schedule 07.05.2013
comment
Меня попросил об этом мой старший, и даже если я использую MaskTextBox, какую маску я должен назначить для шаблонов дефисов   -  person Yogesh    schedule 07.05.2013
comment
Использование модели MVVM, поэтому код диалогового окна должен быть пустым. Это утверждение неверно.   -  person H.B.    schedule 07.05.2013
comment
Х.Б. пожалуйста, прочтите этот stackoverflow.com/questions/6421372/   -  person Yogesh    schedule 07.05.2013


Ответы (2)


Определение свойства: мы должны подсчитывать символы в строке, не включая дефисы. Индекс вставки не может быть установлен здесь, потому что OnPropertyChanged еще не вызывается, поэтому TextBox.Text еще содержит старое значение, и вы не можете установить значение, превышающее длину текста:

 private string _serial;
 public string Serial
 {
     get { return _serial; }
     set
     {
         if (_serial != value)
         {
             _serial = value;
             int res = 0;
             int hyphensCount = _serial.Count(c => c.Equals('-'));
             Math.DivRem(_serial.Length - hyphensCount, 4, out res);
             if (res == 0)
                 _serial = string.Format("{0}-", _serial);
             OnPropertyChanged("Serial");
         }
     }
 }

Поведение – зарегистрируйтесь на событии TextChanged и переместите курсор в конец текста:

 public class MoveCaretToEndBehavior: Behavior<TextBox>
{
    protected override void OnAttached()
    {
        AssociatedObject.TextChanged += new TextChangedEventHandler(AssociatedObject_TextChanged);
    }

    void AssociatedObject_TextChanged(object sender, TextChangedEventArgs e)
    {
        AssociatedObject.CaretIndex = AssociatedObject.Text.Length;
    }
}

Текстовое поле + поведение

<TextBox Text="{Binding Serial,UpdateSourceTrigger=PropertyChanged}">
        <i:Interaction.Behaviors>
            <local:MoveCaretToEndBehavior />
        </i:Interaction.Behaviors>


</TextBox>
person user1064519    schedule 07.05.2013

Вы можете сделать это с помощью свойства в вашей модели представления, как показано ниже. Однако вы обнаружите, что курсор в каретке текстового поля не перемещается к последнему индексу, и, поскольку Caretindex не является привязываемым, вам нужно создать присоединенное свойство для привязки к индексу.

        private string _serial;

        public string Serial
        {
            get { return _serial; }
            set
            {
                if (_serial != value)
                {
                    _serial = value;
                    int res = 0;
                    Math.DivRem(_serial.Length, 4, out res);
                    if (res == 0)
                        Serial = string.Format("{0}-", _serial);
                    CaretIndex = _serial.Lenght - 1;
                    RaisePropertyChanged("Serial");
                }
            }
        }

Вот код xaml, который вам нужен.

<Window x:Name="root" x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="WpfApplication1"
        Title="MainWindow" Height="350" Width="525">
    <TextBox
        Text="{Binding ElementName=root, Path=Serial, UpdateSourceTrigger=PropertyChanged}"
        local:TextIndexBinder.Index="{Binding ElementName=root, Path=Index}"
        />
</Window>
person Bruno Silva    schedule 07.05.2013
comment
установочная часть свойства будет вызываться, когда я потеряю фокус из текстового поля, которое мне не нужно. я хочу эффект, пока пользователь нажимает клавишу - person Yogesh; 07.05.2013
comment
Обратите внимание на UpdateSourceTrigger в привязке. Он обновляется немедленно. - person Bruno Silva; 07.05.2013