Reputation: 88197
I will like to validate user entry to ensure they are integers. How can I do it? I thought of using IDataErrorInfo
which seems like the "correct" way to do validation in WPF. So I tried implementing it, in my ViewModel.
But the thing is my text box is bound to an integer field, and there isn't any need to validate if an int
is an int
. I noticed that WPF automatically adds a red border around the textbox to notify the user of the error. The underlying property doesn't change to an invalid value. But I would like to notify the user of this. How can I do it?
Upvotes: 14
Views: 71736
Reputation: 41
Here is how to create a numeric field in WPF, using the regular expressions.
XAML:
<TextBox PreviewTextInput="NumberValidationTextBox"></TextBox>
Code behind:
private void NumberValidationTextBox(object sender, TextCompositionEventArgs e)
{
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
Upvotes: 0
Reputation: 1118
if you are working in WPF Better to use PreviewTextInput event which support all platforms and from presentationcore.dll
here is the example:
private void TextBox_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
if ((e.Text) == null || !(e.Text).All(char.IsDigit))
{
e.Handled = true;
}
}
Upvotes: 0
Reputation: 121
We can do validation on text box changed event. The following implementation prevents keypress input other than numeric and one decimal point.
private void textBoxNumeric_TextChanged(object sender, TextChangedEventArgs e)
{
TextBox textBox = sender as TextBox;
Int32 selectionStart = textBox.SelectionStart;
Int32 selectionLength = textBox.SelectionLength;
String newText = String.Empty;
int count = 0;
foreach (Char c in textBox.Text.ToCharArray())
{
if (Char.IsDigit(c) || Char.IsControl(c) || (c == '.' && count == 0))
{
newText += c;
if (c == '.')
count += 1;
}
}
textBox.Text = newText;
textBox.SelectionStart = selectionStart <= textBox.Text.Length ? selectionStart : textBox.Text.Length;
}
Upvotes: 9
Reputation: 556
Another way is simply to not allow values that are not integers. The following implementation is a little bit sucky, and I would like to abstract it later on in order for it to be more reusable, but here is what I did:
in the code behind in my view (I know this is might hurt if you are a hardcore mvvm ;o) ) I defined the following functions :
private void NumericOnly(System.Object sender, System.Windows.Input.TextCompositionEventArgs e)
{
e.Handled = IsTextNumeric(e.Text);
}
private static bool IsTextNumeric(string str)
{
System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("[^0-9]");
return reg.IsMatch(str);
}
And in the XAML view, every textbox that was only supposed to accept integers was defined like this:
<TextBox Padding="2" TextAlignment="Right" PreviewTextInput="NumericOnly" Text="{Binding xxx.yyyy}" MaxLength="1" />
The key attribute being PreviewTextInput
Upvotes: 18
Reputation: 4502
The red border you've seen is actually a ValidationTemplate, which you can extend and add a info for the user. See this example:
<UserControl.Resources>
<ControlTemplate x:Key="validationTemplate">
<Grid>
<Label Foreground="Red" HorizontalAlignment="Right" VerticalAlignment="Center">Please insert a integer</Label>
<Border BorderThickness="1" BorderBrush="Red">
<AdornedElementPlaceholder />
</Border>
</Grid>
</ControlTemplate>
</UserControl.Resources>
<TextBox Name="tbValue" Validation.ErrorTemplate="{StaticResource validationTemplate}">
Upvotes: 16