Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Keeping it regular

, 4 Apr 2011 CPOL
Rate this:
Please Sign up or sign in to vote.
Adding Regular Expression functionality in your TextBox.

Last week, I posted an example of using a Regular Expression to control the input of numbers into a TextBox. A couple of my fellow disciples commented that they’d just use a Regular Expression Behavior or DP to control the input of the text. Now, there are a couple of reasons that I’d use the dedicated NumericTextBoxBehavior.

The first reason is that it’s a simple control for those that aren’t comfortable writing Regular Expressions. After all, why should you write a complex Regular Expression when I can write one for you?

The second reason is that the numeric control is internationalised from the get-go. I’ve already taken care of sorting out the whole internationalised decimal place issue, so you don’t have to worry about it with your Regular Expression.

Saying that, the Regular Expression behavior is a cracking idea, and one I could kick myself for not thinking of earlier. So, in order to add Regular Expression functionality in your TextBox, all you need do is add the following code:

namespace Goldlight.Base.Behaviors
{
  using System.Linq;
  using System.Windows.Controls;
  using System.Windows.Interactivity;
  using System.Windows;
  using System.Windows.Input;
  using System.Text.RegularExpressions;

  /// <span class="code-SummaryComment"><summary>
</span>  /// Apply this behavior to a TextBox to ensure that input matches a regular
  /// expression.
  /// <span class="code-SummaryComment"><para>
</span>  /// <span class="code-SummaryComment"><remarks>
</span>  /// In the view, this behavior is attached in the following way:
  /// <span class="code-SummaryComment"><code>
</span>  /// <span class="code-SummaryComment"><TextBox Text="{Binding Price}">
</span>  ///   <span class="code-SummaryComment"><i:Interaction.Behaviors>
</span>  ///   <span class="code-SummaryComment"><gl:RegularExpressionTextBoxBehavior
  ///    Mask="^([\(]{1}[0-9]{3}[\)]{1}[ ]{1}[0-9]{3}[\-]{1}[0-9]{4})$" />
</span>  ///   <span class="code-SummaryComment"></i:Interaction.Behaviors>
</span>  /// <span class="code-SummaryComment"></TextBox>
</span>  /// <span class="code-SummaryComment"></code>
</span>  /// <span class="code-SummaryComment"><para>
</span>  /// Add references to System.Windows.Interactivity to the view to use
  /// this behavior.
  /// <span class="code-SummaryComment"></para>
</span>  /// <span class="code-SummaryComment"></remarks>
</span>  public class RegularExpressionTextBoxBehavior : Behavior<TextBox>
  {
    /// <span class="code-SummaryComment"><summary>
</span>    /// Gets or sets the regular expression mask.
    /// <span class="code-SummaryComment"></summary>
</span>    public string Mask { get; set; }

    #region Overrides
    protected override void OnAttached()
    {
      base.OnAttached();

      AssociatedObject.PreviewTextInput += AssociatedObject_PreviewTextInput;
#if !SILVERLIGHT
      DataObject.AddPastingHandler(AssociatedObject, OnClipboardPaste);
#endif
    }

    protected override void OnDetaching()
    {
      base.OnDetaching();
      AssociatedObject.PreviewTextInput -= AssociatedObject_PreviewTextInput;
#if !SILVERLIGHT
      DataObject.RemovePastingHandler(AssociatedObject, OnClipboardPaste);
#endif
    }
    #endregion

#if !SILVERLIGHT
    /// <span class="code-SummaryComment"><summary>
</span>    /// Handle paste operations into the textbox to ensure that the behavior
    /// is consistent with directly typing into the TextBox.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="sender">The TextBox sender.</param>
</span>    /// <span class="code-SummaryComment"><param name="dopea">Paste event arguments.</param>
</span>    /// <span class="code-SummaryComment"><remarks>This operation is only available in WPF.</remarks>
</span>    private void OnClipboardPaste(object sender, DataObjectPastingEventArgs dopea)
    {
      string text = dopea.SourceDataObject.GetData(dopea.FormatToApply).ToString();

      if (!string.IsNullOrWhiteSpace(text) && !Validate(text))
        dopea.CancelCommand();
    }
#endif

    /// <span class="code-SummaryComment"><summary>
</span>    /// Preview the text input.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="sender">The TextBox sender.</param>
</span>    /// <span class="code-SummaryComment"><param name="e">The composition event arguments.</param>
</span>    void AssociatedObject_PreviewTextInput(object sender, TextCompositionEventArgs e)
    {
      e.Handled = !Validate(e.Text);
    }

    /// <span class="code-SummaryComment"><summary>
</span>    /// Validate the contents of the textbox with the new content to see if it is
    /// valid.
    /// <span class="code-SummaryComment"></summary>
</span>    /// <span class="code-SummaryComment"><param name="value">The text to validate.</param>
</span>    /// <span class="code-SummaryComment"><returns>True if this is valid, false otherwise.</returns>
</span>    protected bool Validate(string value)
    {
      TextBox textBox = AssociatedObject;

      string pre = string.Empty;
      string post = string.Empty;

      if (!string.IsNullOrWhiteSpace(textBox.Text))
      {
        pre = textBox.Text.Substring(0, textBox.SelectionStart);
        post = textBox.Text.Substring(textBox.SelectionStart + textBox.SelectionLength,
          textBox.Text.Length - (textBox.SelectionStart + textBox.SelectionLength));
      }
      else
      {
        pre = textBox.Text.Substring(0, textBox.CaretIndex);
        post = textBox.Text.Substring(textBox.CaretIndex,
          textBox.Text.Length - textBox.CaretIndex);
      }
      string test = string.Concat(pre, value, post);

      string pattern = Mask;

      if (string.IsNullOrWhiteSpace(pattern))
        return true;

      return new Regex(pattern).IsMatch(test);
    }
  }
}

As you can see, it’s similar in code to the other behaviour. The only real difference in it is that it has a mask string which is used to add the Regular Expression text.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Pete O'Hanlon
CEO
United Kingdom United Kingdom
A developer for over 30 years, I've been lucky enough to write articles and applications for Code Project as well as the Intel Ultimate Coder - Going Perceptual challenge. I live in the North East of England with 2 wonderful daughters and a wonderful wife.
 
I am not the Stig, but I do wish I had Lotus Tuned Suspension.
Follow on   Twitter   Google+

Comments and Discussions

 
SuggestionRegex users cannot be trusted. PinmemberDontSailBackwards25-Jan-15 16:48 
GeneralRe: Regex users cannot be trusted. PinprotectorPete O'Hanlon25-Jan-15 22:14 
GeneralMy vote of 5 PinmemberDontSailBackwards25-Jan-15 16:33 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150327.1 | Last Updated 4 Apr 2011
Article Copyright 2011 by Pete O'Hanlon
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid