tags:

views:

1204

answers:

2

We all know how sucky WPF validation is out of the box. I am trying a very simple thing and for some reason it is always failing. I have a TextBox and my only requirement is to validate that the user inputs something in the TextBox. The TextBox is bound to a Customer object with FirstName and LastName properties.

Here is the XAML code:

            <TextBox Style="{StaticResource TextBoxStyle}" Grid.Column="1"  Grid.Row="0" Height="20" Width="100" Margin="10">
                <TextBox.Text>
                    <Binding Path="FirstName" >
                        <Binding.ValidationRules>
                            <ExceptionValidationRule />
                        </Binding.ValidationRules>
                    </Binding>
                </TextBox.Text>

            </TextBox>

Here is the Customer class FirstName property:

public string FirstName
        {
            get { return _firstName;}
            set
            {
                if(String.IsNullOrEmpty(value))
                    throw new ApplicationException("FirstName cannot be null or empty!");
                _firstName = value; 

                OnPropertyChanged("FirstName");
            }
        }

Even though I am throwing an exception if the FirstName (value) is null or empty it is only handled if I type something in the TextBox and then delete it and then tab off. The reason is that it is dependent on the property changed event. But even if I put that TextBox binding on Focus it does not fire the validation.

UPDATE:

One of the ugliest ways to handle this issue is to assign the String.Empty to the TextBoxes on the Window.Loaded event:

 void AddCustomerWindow_Loaded(object sender, RoutedEventArgs e)
        {
            // get all the textboxes and set the property to empty strings! 

            txtFirstName.Text = String.Empty;
            txtLastName.Text = String.Empty; 
        }

Here is the code for binding:

 public AddCustomerWindow()
        {
            InitializeComponent();

            this.Loaded += new RoutedEventHandler(AddCustomerWindow_Loaded);

            gvAddCustomer.DataContext = new Customer();  
        }
A: 

In your example XAML code, I don't see any Binding. I presume the Text property of the TextBox is bound to FirstName?

Secondly: is FirstName initialized at first, or does it return null when retrieved by the TextBox? Binding to a null value always gives strange behaviors...

Try saying this in the property:

   public string FirstName
    {
        get
        {
            if (_firstName == null)
            {
                _firstName = String.Empty;
            }
            return _firstName;
        }
        set
        {
            if (String.IsNullOrEmpty(value))
                throw new ApplicationException("FirstName cannot be null or empty!");
            _firstName = value;

            OnPropertyChanged("FirstName");
        }
    }
As, you can see the updated code the TextBox is bound to a new Customer object. When I type nothing in the TextBox and Tab to a different control nothing happens. It should fire the validation but it does not! The only way to fire the validation is if I manually assign the .Text property of TextBox in the Window.Loaded event.
azamsharp
Yes, I see. And when the FirstName is called, does it return a String or a null value?
It returns null!
azamsharp
A: 

I think you just need to specify the UpdateSourceTrigger and you should be good to go (note: I also usually add the ValidatesOnDataErrors=true):

GS