Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I'm having this really simple class, lets call it Customer. It look like this:

namespace TestValidation
{
     class Customer
     {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                if (String.IsNullOrEmpty(value))
                {
                    throw new Exception("Customer name is mandatory.");
                }
            }
        }
    }
}

Now, I've created a basic form, where the user can add customers to the database. The form contain simple TextBox, bounded to the Name property of Customer, and an "Add" button.

The XAML code is:

<Window x:Class="TestValidation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:TestValidation"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
<TextBox Margin="119,86,107,194" Name="CustomerName"
        Text="{Binding Path=Customer.Name, 
                ValidatesOnExceptions=True, 
                ValidatesOnDataErrors=True,
                UpdateSourceTrigger=PropertyChanged,
                NotifyOnValidationError=True}"
    />
        <Button Content="Add" HorizontalAlignment="Left" Margin="204,176,0,0" VerticalAlignment="Top" Width="74"/>
    </Grid>
</Window> 

From the setter of the Name property, you can understand that the name is mandatory for me, so I want an validation event to rise if the Name TextBox left blank. By validation rules of WPF - once the user focus out of the textbox, and there's no value over there - it should change the border color to red. For some reason - this is not happening, and I don't have a clue why. What is wrong in my process?

Now, I've read so many good articles about Validation in WPF (like Enforcing Complex Business Data Rules with WPF, Data validation in WPF and Validation in Windows Presentation Foundation), but none of them helped me solving my problem.

Eventually, I want the form to look like the form in Brian Noyes excellent article over the first link (Don't have 10 credits, so I can't attach a photo... sorry).

I'll be grateful if someone can explain to me how it really works.

Important note - I'm working with .Net framework 4, so I need a solution that suits this version.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
227 views
Welcome To Ask or Share your Answers For Others

1 Answer

I would definitely recommend using IDataErrorInfo for WPF validation since WPF already understands how to use it, and its easy to implement.

To start with, add the interface to the class containing the data you want to validate. The required methods will probably look something like this:

public class Customer : IDataErrorInfo
{
    ...

    #region IDataErrorInfo Members

    string IDataErrorInfo.Error
    {
        get { return null; }
    }

    string IDataErrorInfo.this[string columnName]
    {
        get
        {
            if (columnName == "Name")
            {
                // Validate property and return a string if there is an error
                if (string.IsNullOrEmpty(Name))
                    return "Name is Required";
            }

            // If there's no error, null gets returned
            return null;
        }
    }
    #endregion
}

Next, you need to set ValidatesOnDataErrors=True in your TextBox binding so it runs the validation whenever the Name property changes:

<TextBox Text="{Binding Path=Customer.Name, ValidatesOnDataErrors=True}" ... />

And finally, create a Validation Template in your XAML to tell WPF how to draw a validation error. Here's the style/template I usually use:

<!-- ValidatingControl Style -->
<Style TargetType="{x:Type FrameworkElement}" x:Key="ValidatingControl">
    <Style.Triggers>
        <Trigger Property="Validation.HasError" Value="True">
            <Setter Property="ToolTip" Value="{Binding 
                Path=(Validation.Errors)[0].ErrorContent, 
                RelativeSource={x:Static RelativeSource.Self}}" />
        </Trigger>
    </Style.Triggers>
</Style>

Also, be sure your Customer class implements INotifyPropertyChanged so it correctly responds to UI updates. I don't see that in your code, but often people leave that out for simplicity :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...