Click here to Skip to main content
14,382,805 members

Number Only Behavior for WPF

Rate this:
5.00 (10 votes)
Please Sign up or sign in to vote.
5.00 (10 votes)
1 Oct 2015CPOL
Presents a behavior to prevent entry of anything but digits into a control

Introduction

I have struggled to try and create a good behavior to allow users only to enter number keys. Of course, most of my problem was I did not know the right approach. Seemed that the event to use was the KeyPress event, but it is not because there is no easy way to distinguish if the user has entered a digit or not because the event arguments return only the key, and not the resulting character. The only good way that I know of is to attach to the TextInput event. In this event, I use LINQ to check each if any of the characters of the string are not a digit, and if they are not, set the Handled equal to true. I have seen a lot of implementations that use a Regular Expression to check if all the characters are digits, but I am sure that this is a lot heavier than just checking that all are digits.

I also use the DataObject.AddPastingHandler to add an event handler that will ensure that pasted values are text and only contain digits.

The Code

There is one DependencyProperty for this behavior:

public static readonly DependencyProperty IsEnabledProperty =
  DependencyProperty.RegisterAttached("IsEnabled", typeof(bool),
  typeof(NumberOnlyBehaviour), new UIPropertyMetadata(false, OnValueChanged));

public static bool GetIsEnabled(Control o) { return (bool)o.GetValue(IsEnabledProperty); }

public static void SetIsEnabled(Control o, bool value) { o.SetValue(IsEnabledProperty, value); }

As usual for my properties on behaviours, I try to use something familiar, and a bool IsEnabled seemed to be an obvious name for the property. To use it just need to set IsEnabled to true.

The event handler for this DespendencyProperty is OnValueChanged. The code is as follows:

private static void OnValueChanged(DependencyObject dependencyObject,
  DependencyPropertyChangedEventArgs e)
{
 var uiElement = dependencyObject as Control;
 if (uiElement == null) return;
 if (e.NewValue is bool && (bool)e.NewValue)
 {
  uiElement.PreviewTextInput += OnTextInput;
  uiElement.PreviewKeyDown += OnPreviewKeyDown;
  DataObject.AddPastingHandler(uiElement, OnPaste);
 }

 else
 {
  uiElement.PreviewTextInput -= OnTextInput;
  uiElement.PreviewKeyDown -= OnPreviewKeyDown;
  DataObject.RemovePastingHandler(uiElement, OnPaste);
 }
}

Basically this event handler subscribes to the two events that will filter out any user input that is not a number, and also add a handler that will deal with pasting of text when the behavior is enabled by setting the IsEnabled equal to true, and otherwise removes the handlers.

The two keyboard event handlers are:

private static void OnTextInput(object sender, TextCompositionEventArgs e)
{
 if (e.Text.Any(c => !char.IsDigit(c))) { e.Handled = true; }
}

private static void OnPreviewKeyDown(object sender, KeyEventArgs e)
{
 if (e.Key == Key.Space)e.Handled = true;
}

The OnPreviewKeyDown event handler is required because the PreviewTextInput event does not fire when the space key is pressed, so also have include an event handler for the PreviewKeyDown. All other key presses cause a change in the TextInput, so the checking if the text contains a non-digit value. Unfortunately it is very difficult to know the effect of the key press on the KeyDown or KeyUp events because the KeyEventArgs only provide the enumeration of the Key and not the effect, so handling only one KeyPress event is very hard to implement.

And finally the paste handler:

private static void OnPaste(object sender, DataObjectPastingEventArgs e)
{
 if (e.DataObject.GetDataPresent(DataFormats.Text))
 {
  var text = Convert.ToString(e.DataObject.GetData(DataFormats.Text)).Trim();
  if (text.Any(c => !char.IsDigit(c))) { e.CancelCommand(); }
 }
 else
 {
  e.CancelCommand();
 }
}

How to use this behaviour

To use this behavior is very easy. On the control you want to allow only numbers, you would add this behavior as shown in bold:

<TextBox Style="{StaticResource EditFormTextBoxNumericStyle}"

	behaviours:NumberOnlyBehaviour.IsEnabled="True"

	Text="{Binding Sequence,
		UpdateSourceTrigger=PropertyChanged,
		ValidatesOnDataErrors=True}" />

Image 1

History

  • 1st October, 2015: Initial version
  • 3 March 2016 added updated source code to handle the space key as recommended by George Swan.

License

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

Share

About the Author

Clifford Nelson
Software Developer (Senior) Clifford Nelson Consulting
United States United States
Has been working as a C# developer on contract for the last several years, including 3 years at Microsoft. Previously worked with Visual Basic and Microsoft Access VBA, and have developed code for Word, Excel and Outlook. Started working with WPF in 2007 when part of the Microsoft WPF team. For the last eight years has been working primarily as a senior WPF/C# and Silverlight/C# developer. Currently working as WPF developer with BioNano Genomics in San Diego, CA redesigning their UI for their camera system. he can be reached at qck1@hotmail.com.

Comments and Discussions

 
QuestionWorking good Pin
hbehar4-Jun-17 1:10
memberhbehar4-Jun-17 1:10 
AnswerRe: Working good Pin
Clifford Nelson7-Jun-17 7:36
mvaClifford Nelson7-Jun-17 7:36 
QuestionSpace key? Pin
George Swan4-Oct-15 21:41
memberGeorge Swan4-Oct-15 21:41 
AnswerRe: Space key? Pin
Clifford Nelson3-Mar-16 11:54
mvaClifford Nelson3-Mar-16 11:54 
QuestionI've done it in the model Pin
marc borgers3-Oct-15 22:25
membermarc borgers3-Oct-15 22:25 
AnswerRe: I've done it in the model Pin
Clifford Nelson4-Oct-15 10:01
mvaClifford Nelson4-Oct-15 10:01 

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

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

Tip/Trick
Posted 1 Oct 2015

Stats

19.6K views
669 downloads
17 bookmarked