I want validate textbox IN WPF MVVM pattern server side to allow number with decimal value, like
1O.10
10.01
2.22
3.444
1234.676
but not alphanumerics like
FHFJ
XTHKX
SPECIAL CHARATER(@#$$)
67..8787
This my code snippet
I want validate textbox IN WPF MVVM pattern server side to allow number with decimal value, like
1O.10
10.01
2.22
3.444
1234.676
but not alphanumerics like
FHFJ
XTHKX
SPECIAL CHARATER(@#$$)
67..8787
This my code snippet
A View Model based solution may look as following:
double _MyValidNumber;
string _MyNumber;
public string MyNumber
{
get
{
return _MyNumber;
}
set
{
_MyNumber = value;
double _temp;
string toBexamined = value;
if (!toBexamined.Contains("."))
{
toBexamined += ".0";
}
if (toBexamined.EndsWith("."))
{
toBexamined += "0";
}
if (!double.TryParse(toBexamined, out _temp))
{
_MyNumber = _MyValidNumber.ToString();
}
else
{
_MyValidNumber = _temp;
}
NotifyPropertyChanged(nameof(MyNumber)); }
}
I would like to present a solution that is based on using a User Control - TextBoxDouble.
How we use it :
<local:TextBoxDouble Number="{Binding SimpleNumber,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"/>
the TextBoxDouble XAML is as following:
<UserControl x:Class="Problem19_ValidateANumber.TextBoxDouble"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Problem19_ValidateANumber"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" Name="Parent">
<Grid>
<TextBox Text="{Binding ElementName=Parent,Path=Text,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay}" />
</Grid>
</UserControl>
In the Code Behind we have defined 2 dependency properties: Text and Number. The 2 properties exchange the data. The Text Property is for the UI side and the Number is for the View Model property side.
public partial class TextBoxDouble : UserControl
{
public TextBoxDouble()
{
InitializeComponent();
}
public string Text
{
get { return (string)GetValue(TextProperty); }
set {
SetValue(TextProperty, value);
SetValue(TextProperty, value);
}
}
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register("Text", typeof(string), typeof(TextBoxDouble),
new PropertyMetadata(string.Empty, new PropertyChangedCallback(TextPropertyChanged)));
public double Number
{
get { return (double)GetValue(NumberProperty); }
set
{
SetValue(NumberProperty, value);
}
}
public static readonly DependencyProperty NumberProperty =
DependencyProperty.Register("Number", typeof(double), typeof(TextBoxDouble),
new PropertyMetadata(double.NaN, new PropertyChangedCallback(NumberPropertyChanged)));
private static void TextPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
TextBoxDouble ours = (TextBoxDouble)obj;
if (e.NewValue == e.OldValue) return;
double _temp;
string toBexamined = (string)e.NewValue;
if (!toBexamined.Contains("."))
{
toBexamined += ".0";
}
if (toBexamined.EndsWith("."))
{
toBexamined += "0";
}
if (!double.TryParse(toBexamined, out _temp))
{
ours.SetValue(TextProperty, ours.Number.ToString());
}
else
{
ours.SetValue(NumberProperty, _temp);
}
}
private static void NumberPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
TextBoxDouble ours = (TextBoxDouble)obj;
if (e.NewValue == e.OldValue) return;
ours.SetValue(TextProperty, ours.Number.ToString());
}
}
Similar to what @Gilad Waisel suggested. I think the most simplest ways would be just to extend the TextBox class and enter your desired validation into the TexhChangeEvent:
public class TextBoxDecimal : TextBox
{
readonly string CurrentSeperator;
public TextBoxDecimal()
{
CultureInfo cultureInfo = CultureInfo.CurrentCulture;
CurrentSeperator = cultureInfo.NumberFormat.CurrencyDecimalSeparator;
}
protected override void OnTextInput(TextCompositionEventArgs e)
{
if (double.TryParse(e.Text, out var value))
base.OnTextInput(e);
else if (e.Text == CurrentSeperator && !Text.Any(x => x == CurrentSeperator[0]))
base.OnTextInput(e);
}
}
This is not conflicting with MVVM however does operate ONLY on the UI side.
Below is the working code to accept only double value:
decimal _MyValidNumber;
string _MyNumber;
public string MyNumber
{
get
{
return _MyNumber;
}
set
{
if (decimal.TryParse(value, out decimal result))
{
_MyValidNumber = result;
_MyNumber = value;
}
else
{
_MyNumber = "";
}
NotifyPropertyChanged(nameof(_MyNumber));
}
}