在WPF中绑定数据时进行验证

在WPF中绑定数据时进行验证,wpf,validation,mvvm,Wpf,Validation,Mvvm,我已经用WPF(MVVM)构建了一个应用程序,并添加了验证。以下是我的结果: 您会注意到输入文本框周围的红色斜纹。问题是,我不想在启动表单时让客户端面对验证错误。输入数据或按Submit键时最好 在SO上有一些类似的问题,但尚未找到合适的解决方案。 (初始化时重置每个控件不是解决方案) 所以问题是如何启动表单和: 选项A:(轻松)重置验证 选项B:在绑定之后才调用验证 选项C:其他不错的解决方案 下载代码: <Window x:Class="Validation.MainWindow"

我已经用WPF(MVVM)构建了一个应用程序,并添加了验证。以下是我的结果:

您会注意到输入文本框周围的红色斜纹。问题是,我不想在启动表单时让客户端面对验证错误。输入数据或按Submit键时最好

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

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

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

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

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

下载代码:

<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>
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
    }

查看代码:

<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>
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
    }
型号代码:

<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>
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
    }
公共类FormModel:INotifyPropertyChanged,IDataErrorInfo
{
#区域notifypropertychanged
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged(字符串propertyName)
{
PropertyChangedEventHandler处理程序=this.PropertyChanged;
if(处理程序!=null)
{
var e=新的PropertyChangedEventArgs(propertyName);
处理者(本,e);
}
}
#端区
#区域数据错误信息
公共字符串错误
{
获取{return null;}
}
公共字符串此[string columnName]
{
得到
{
开关(列名称)
{
案例“名称”:
if(string.IsNullOrEmpty(Name))
{
返回“名称为必填项”;
}
打破
案例“年龄”:
如果(年龄<18岁| |年龄>50岁)
{
return“你在开玩笑吗?”;
}
打破
}
返回null;
}
}
#端区
#区域属性
私有字符串名称;
公共字符串名称{get{return Name;}set{Name=value;OnPropertyChanged(“Name”);}
私人互联网;
public int Age{get{return Age;}set{Age=value;OnPropertyChanged(“Age”);}
#端区
}
解决方案(目前)


?
*

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

首先,如果您的规则规定first和lastname不应为空- 用户有权看到验证错误

我所做的是对空/初始值使用ValidationTemplate,所以 用户只看到一个“*”作为必填字段


是完整的答案

我很喜欢你的方法,我会尝试一下。尝试一下,并将结果添加到问题中。