0
votes

I have a textfield in WPF and i want to validate the user input, i have found lots of examples that do bits of what i want but none that do it all.

It has to only allow numeric numbers (0-9) Only one decimal place Not allow multiple '.' which most solutions seem to allow, Minimum number entry must be Maximum 999.9

Best solution i found so far is using a regex

new Regex(@"[^0-9.]+") 

but this obviously doesn't limit number of decimal places or number of decimal points. Also no min or max

Can only one point me in the correct direction?

Thanks

2

2 Answers

0
votes

A cleaner solution might be to bind the text box to a double (or decimal) value which will give you the automatic digit and decimal point rules and add a [Range] attribute of your minimum and maximum values:

[Range(0, 999.9), "Error message"]
public double myValue { get; set; }

Or, if you want to actually prevent invalid input being entered in the first place, implement the OnKeyDown event handler for the text box and try to convert the input to a number. If it fails reject the input or if it succeeds but the number is outside your range reject the input. This is not an ideal solution.

0
votes

I commonly use this approach for it's simplicity and flexibility. Just a humble concoction of Regex and plain-old conditional logic. This same pattern can be applied to almost any form of text input validation.

The ViewModel

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Text.RegularExpressions;

namespace WpfApplication7
{
    public class ViewModel : INotifyPropertyChanged
    {
        Regex _inputRegex;
        public ViewModel()
        {
            _inputRegex = new Regex(@"^([0-9])+(([.])?([0-9])+)?$");
        }
        private string _input = "0";
        public string Input
        {
            get
            {
                return _input;
            }
            set
            {
               _input = value;
               RaisePropertyChanged("Input");
               RaisePropertyChanged("InputValid");
            }
        }
        public bool InputValid {
            get
            {
                if(_inputRegex.IsMatch(_input))
                {
                    //If regex pattern is satisfied, this value is safe
                    double value = Convert.ToDouble(_input);

                    //so just apply conditional logic here
                    return value >= 0 && value <= 999.9;
                }
                else
                {
                    return false;
                }
            }        
        }
        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string property)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
        }
    }
}

The View

<Window x:Class="WpfApplication7.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication7"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:ViewModel />
    </Window.DataContext>
    <Window.Resources>
        <Style TargetType="FrameworkElement" >
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
        </Style>
        <Style TargetType="TextBox">
            <Setter Property="Width" Value="100" />
            <Setter Property="Height" Value="24" />
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="Margin" Value="10" />
        </Style>
        <Style  TargetType="TextBlock" x:Key="default_textblock">
            <Setter Property="Height" Value="18" />
            <Setter Property="Margin" Value="10" />
        </Style>
        <Style TargetType="TextBlock" x:Key="error_textblock" BasedOn="{StaticResource default_textblock}">
            <Setter Property="Foreground" Value="Red" />
        </Style>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="60" />
            <RowDefinition Height="60" />
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <TextBlock Text="Enter input: " Style="{StaticResource default_textblock}" />
            <TextBox Text="{Binding Input, UpdateSourceTrigger=PropertyChanged}" />
        </StackPanel>
        <TextBlock Grid.Row="1" Text="Input not valid. Please enter a number between 0 and 999.9" >
            <TextBlock.Style>
                <Style TargetType="TextBlock" BasedOn="{StaticResource error_textblock}">
                    <Setter Property="Visibility" Value="Hidden" />
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding InputValid}" Value="False">
                            <Setter Property="Visibility" Value="Visible" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </TextBlock.Style>
        </TextBlock>
    </Grid>
</Window>