在WPF中绑定数据时的验证

时间:2012-02-01 08:46:45

标签: wpf validation mvvm

我在WPF(MVVM)中构建了一个应用程序并添加了验证。这是我的结果:

enter image description here

你会注意到输入文本框周围的红色绅士。问题是我不想在启动表单时遇到验证错误的客户端。输入数据或按提交最好。

在SO上有一些类似的问题但尚未找到合适的解决方案。 (重置初始化时的每个控件都没有解决方案)

所以问题是如何启动表单和:

选项A :(轻松)重置验证

选项B:在绑定之后不要调用验证

选项C:其他不错的解决方案

下载代码:

here

查看代码:

<Window x:Class="Validation.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="150" Width="250">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition Height="*"></RowDefinition>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="80"></ColumnDefinition>
            <ColumnDefinition></ColumnDefinition>
        </Grid.ColumnDefinitions>
        <!-- Name -->
        <Label Grid.Column="0" Grid.Row="0">Name</Label>
        <TextBox Grid.Column="1" Grid.Row="0"
                 Text="{Binding Model.Name, UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"></TextBox>
        <!-- Age -->
        <Label Grid.Column="0" Grid.Row="1">Age</Label>
        <TextBox Grid.Column="1" Grid.Row="1"
                 Text="{Binding Model.Age, UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"></TextBox>
        <!-- Submit/Cancel -->
        <StackPanel Grid.Column="1" Grid.Row="2" FlowDirection="LeftToRight">
            <Button>Cancel</Button>
            <Button>Submit</Button>
        </StackPanel>
    </Grid>
</Window>

ViewModel代码:

public class FormViewModel
{
    #region constructors
    public FormViewModel()
    {
        Model = new FormModel();
    }
    #endregion

    #region properties
    public FormModel Model { get; set; }
    #endregion

}

型号代码:

   public class FormModel : INotifyPropertyChanged, IDataErrorInfo
    {
        #region notifypropertychanged
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                var e = new PropertyChangedEventArgs(propertyName);
                handler(this, e);
            }
        }
        #endregion

        #region dataerrorinfo
        public string Error
        {
            get { return null; }
        }

        public string this[string columnName]
        {
            get
            {
                switch (columnName)
                {
                    case "Name":
                        if (string.IsNullOrEmpty(Name))
                        {
                            return "Name is required";
                        }
                        break;
                    case "Age":
                        if (Age < 18 || Age > 50)
                        {
                            return "Are you kidding?";
                        }
                        break;
                }
                return null;
            }
        }
        #endregion

        #region properties
        private string name;
        public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } }

        private int age;
        public int Age { get { return age; } set { age = value; OnPropertyChanged("Age"); } }
        #endregion
    }

解决方案(目前)

enter image description here

<Style x:Key="InputControlDefault" TargetType="{x:Type TextBox}">
    <Setter Property="Validation.ErrorTemplate">
        <Setter.Value>
            <ControlTemplate>
                <DockPanel LastChildFill="True">
                    <TextBlock DockPanel.Dock="Right" 
                    Foreground="black"
                    FontSize="12pt">
                    ?
                    </TextBlock>
                    <AdornedElementPlaceholder/>
                </DockPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Style.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Foreground" Value="Black"/>
        </Trigger>
        <Trigger Property="Validation.HasError" Value="true">
            <Setter Property="ToolTip" Value="test"/>
            <Setter Property="BorderBrush" Value="Red" />
        </Trigger>
        <MultiTrigger>
            <MultiTrigger.Conditions>
                <Condition Property="Validation.HasError" Value="true"/>
                <Condition Property="Text" Value=""/>
            </MultiTrigger.Conditions>
            <Setter Property="BorderBrush" Value="Orange" />
            <Setter Property="Validation.ErrorTemplate">
                <Setter.Value>
                    <ControlTemplate>
                        <DockPanel LastChildFill="True">
                            <TextBlock DockPanel.Dock="Right" Foreground="Black" FontSize="12pt">
                                *
                            </TextBlock>
                            <AdornedElementPlaceholder/>
                        </DockPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="ToolTip" Value="test"/>
        </MultiTrigger>
    </Style.Triggers>
</Style>

1 个答案:

答案 0 :(得分:1)

我几天前回答了一个类似的问题:

  

首先,如果你的规则说第一个和最后一个名字不应该是空的 -   用户看到验证错误的权利。

     

我所做的是将ValidationTemplate用于空/初始值,所以   用户只需看到“*”表示要求的字段。

here是完整的答案