Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
238 views
in Technique[技术] by (71.8m points)

c# - Really simple WPF form data validation - how to?

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

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

1 Reply

0 votes
by (71.8m points)

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 :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...