Search code examples
wpfwpf-controlswpfdatagridwpftoolkitwpf-4.0

Insert hyphen automatically after every 4 characters in a TextBox


I want to implement some thing that when a user enters 4 characters then a hyphen should be added to the text and then again user enter 4 characters and then again hypen should added automatically in WPF.

Note

"I want to implement this behavior when user is typing in the text box (not after textbox has lost focus) beacause the later is very easy to implement"

Using MVVM model, therefore code behind of Dialog should be empty


Solution

  • Property Definition : we should count the characters in the string not including the hyphens Caret index cant be set here because OnPropertyChanged is not being invoked yet, so the TextBox.Text stil contains the old value, and you cant set a value which bigger than the text length:

     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");
             }
         }
     }
    

    Behavior - register to TextChanged event and move the caret to the end of text:

     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 + Behavior

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