TextBox input validation

How can I validate input for my textboxes For example I have an application where I want to input several numbers in the textboxes. The primary validation constraint is that I want the user to be able to input only valid real numbers. Some of the textboxes should contain only positive real numbers. Also I want to be able to do comparisons between the different values (for example I have a minimum speed textbox, and maximum speed textbox, so there's one more rule here: min <= max). Also, if the user is currently editing a textbox, he should be able to cancel the modifications, by pressing escape. How can I do all these with Avalon/WPF


Thanks in advance,
Cosmin.


Answer this question

TextBox input validation

  • blowdart

    Yes <c:DoubleRangeRule Min="0.0" Max="90.0"/> works fine, but then the values are hardcoded, I thought you wanted them to be dynamic.
    I was thinking something in the line of: <local:ValidateMin Motor="Motor">. But I can't get it to work.

    Yes I think that Motor has to be public.


  • LeoFromCanada

    I think you should look into ValidationRule.

    Search this forum or the net.

    Best regards,
    Thomas Andersen


  • CaptainRon

    Here's what I found while searching the net:

    "Binding Sources

    Up to this point, we've used another control as the source for all of our binding examples. In most XAML-based projects, however, you will be binding to sources other than other controls. The key to most data binding is the Source property. In the previous examples, we are using the ElementName property, which is used to bind to a control, instead of using the Source property. For most applications, you will want to bind to more significant sources, such as XML or .NET objects. XAML supports this with its data provider objects. There are two types of data providers built into XAML: ObjectDataProvider and XmlDataProvider. The ObjectDataProvider is used for binding to and from .NET objects, and, not surprisingly, the XmlDataProvider is used to bind to and from XML fragments and documents. You can specify a data provider in the resources section of any XAML container."

    Taken from:

    http://msdn.microsoft.com/library/default.asp url=/library/en-us/dnlong/html/WPFDataBinding_Pt1.asp

    Still, the class isn't documented.

  • hannah_logi

    Taken from the same document:

    "If you want to bind to objects that already exist at runtime or static objects, you cannot use XAML syntax to do it."

    This kindof lets me down. The documentation seems old, I wonder if it still applies...

  • figure8car

    Yes, but you don't do it in XAML. I am talking about the ugly line.

  • VijayTS

    Thanks for the consistent reply. This looks like something I can relate to. :)

    Is it really necessary to have the motor exposed as a public property In my class I have it as a private member field, and there's no other reason for exposing this, other than this.

  • tech222

    Hmm... actually this was one of the original problems I had, not being able to set something defined in code-behind throught XAML:

    how to get Motor :
    CodeBehind[Motor] --------------> XAML

    how to set ValidationRule parameter :
    XAML ------------>CodeBehind[ValidationRule]

    If we can find this, we solved both problems.

  • Neelam

    You can do something like this (note; you need to tweak it, this is only for demonstration):

    XAML:
    <Window x:Class="WindowsApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WindowsApplication1"
    Title="WindowsApplication1" Height="300" Width="300"
    Name="myWindow"
    >
    <StackPanel DataContext="{Binding ElementName=myWindow}">
    <TextBox Text="{Binding Path=Motor.Resolution}" />
    <TextBox Name="tbMin">
    <TextBox.Text>
    <Binding Path="Motor.Min">
    <Binding.ValidationRules>
    <local:ValidateMin />
    </Binding.ValidationRules>
    </Binding>
    </TextBox.Text>
    </TextBox>
    <TextBox Text="{Binding Path=Motor.Max}" />
    </StackPanel>
    </Window>


    Codebehind:
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Shapes;
    using System.Globalization;


    namespace WindowsApplication1
    {
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
    private Motor motor = new Motor();

    public Motor Motor
    {
    get { return motor; }
    set { motor = value; }
    }

    public Window1()
    {
    InitializeComponent();
    }

    protected override void OnInitialized(EventArgs e)
    {
    base.OnInitialized(e);
    (this.tbMin.GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules[0] as ValidateMin).Motor = this.motor;
    }

    }

    public class Motor
    {
    private double resolution;
    private double min;
    private double max;

    public double Resolution
    {
    get { return resolution; }
    set { resolution = value; }
    }

    public double Min
    {
    get { return min; }
    set { min = value; }
    }

    public double Max
    {
    get { return max; }
    set { max = value; }
    }
    }

    public class ValidateMin : ValidationRule
    {
    private Motor motor;

    public Motor Motor
    {
    get { return motor; }
    set { motor = value; }
    }

    public ValidateMin()
    {
    }

    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
    if (Convert.ToDouble(value) > this.Motor.Max)
    return new ValidationResult(false, "Min cannot be bigger that max");
    else
    return new ValidationResult(true, null);
    }
    }

    }

    This is however an ugly line:
    (this.tbMin.GetBindingExpression(TextBox.TextProperty).ParentBinding.ValidationRules[0] as ValidateMin).Motor = this.motor;

    Does anyone know how to pass the value through XAML instead



  • renju

    That dosn't apply, as you can see my example works fine.


  • Smokey I

    Could this sample code solve the ugly line you were talking about

    XAML Snippet:

    <Binding.ValidationRules>
    <c:DoubleRangeRule Min="0.0" Max="90.0"/>
    </Binding.ValidationRules>


    CODE:

    class DoubleRangeRule : ValidationRule
    {
    private double mMin;
    private double mMax;

    public DoubleRangeRule()
    {
    }

    public double Min
    {
    get { return mMin; }
    set { mMin = value; }
    }

    public double Max
    {
    get { return mMax; }
    set { mMax = value; }
    }

    public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
    {
    double val = 0;

    try
    {
    if (((string)value).Length > 0)
    val = double.Parse((string)value);
    }
    catch (Exception e)
    {
    return new ValidationResult(false, "Illegal characters or " + e.Message);
    }

    if ((val < mMin) || (val > mMax))
    {
    return new ValidationResult(false,
    "Please enter a real number in the range: " + mMin + " - " + mMax + ".");
    }

    return new ValidationResult(true, null);
    }
    }

  • hanekhw

    I am having some problems doing this.

    1. I have a 'motor' private field of type 'Motor' in the code behind file. I want to bind to its 'Resolution' property (Motor.Resolution). How do I do this I've tried setting a static resource like: <l:Motor x:Name="motor" x:Key="motorkey" /> and then use the key in the XAML file. But it doesn't work, it's like it has two Motor objects (the private field, and the static resource). How can I bind to it (the private field)

    2. I have two textboxes, for MinSpeed and MaxSpeed. Logically, MinSpeed should not be greater than MaxSpeed. How does the validation rule mechanism come in handy here

    Thanks,
    Cosmin.

  • TextBox input validation