WPF绑定(Binding)下的数据验证IDataErrorInfo

这篇具有很好参考价值的文章主要介绍了WPF绑定(Binding)下的数据验证IDataErrorInfo。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

绑定下的数据验证

WPF中Binding数据校验、并捕获异常信息的三种方式讲到了三种方式,其中使用ValidatinRule的方式比较推荐,但是如果一个类中有多个属性,要为每个属性都要声明一个ValidatinRule,这样做非常麻烦。可以让类继承自IDataErrorInfo来解决这个问题。

IDataErrorInfo基本使用

Data类中具有多个属性

public class Data : IDataErrorInfo
{

    private string _value;

    public string Value
    {
        get { return _value; }
        set { _value = value; }
    }

    private string _myVar;

    public string MyVar
    {
        get { return _myVar; }
        set { _myVar = value; }
    }


    //索引器
    //获得给定属性名称的错误信息
    public string this[string columnName]
    {
        get
        {
            if (columnName == "Value" && this.Value =="123")
            {
                return "出错了~Value~[IDataErrorInfo]";
            }
            if (columnName == "MyVar" && this.MyVar == "123")
            {
                return "出错了~MyVar~[IDataErrorInfo]";
            }
            return string.Empty;
        }
    }

    //获取该对象错误原因
    //该案例没有用到
    public string Error => "对象设置了123";
}

XAML代码
TextBox利用DataContext绑定属性
绑定数据源的方式有4种:Source、ElementName、DataContext、RelativeSource

<Window.DataContext>
    <local:Data/>
</Window.DataContext>

<StackPanel>
    <!--必须设置ValidatesOnDataErrors=True-->
    <TextBox  Text="{Binding Value,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" x:Name="tb"/>
    <TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=tb}"/>
    <Border BorderThickness="3" BorderBrush="Red"/>
    <TextBox Text="{Binding MyVar,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" x:Name="ts"/>
    <TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,ElementName=ts}"/>
</StackPanel>

WPF绑定(Binding)下的数据验证IDataErrorInfo

使用反射与特性

从上面看出,利用索引器和属性名称可以判断是否为某些特性的值,但是这样写仍然太过麻烦,如果一个类中有大量的属性,要为每个属性进行判断,这样会有大量的if语句,可读性和可维护性都不太好。

既然在索引器中我们已经有了属性名称,我们可以利用反射来简化上面的步骤。

  1. 自定义一个Attribute特性类
public class NotValueAttribute : Attribute
{
    public string ValidateValue { get; set; }

    public NotValueAttribute(string value) { ValidateValue = value; }
}
  1. 在重写索引器中的get方法
public string this[string columnName]
{
    get
    {
        PropertyInfo? pInfo = this.GetType().GetProperty(columnName, BindingFlags.Public | BindingFlags.Instance);


        if (pInfo.IsDefined(typeof(NotValueAttribute), false))
        {
            NotValueAttribute attr = (NotValueAttribute)pInfo.GetCustomAttribute(typeof(NotValueAttribute), false);
            //如果属性没有应用该特性
            if (attr == null) { return string.Empty; }
            //如果属性值为空
            else if(pInfo.GetValue(this) == null) { return string.Empty; }
            //如果属性值为定义的ValidateValue
            else if (pInfo.GetValue(this).ToString() == attr.ValidateValue)
            {
                return "字段不能为" + attr.ValidateValue;
            }
        }
        return string.Empty;
    }
}
  1. 分别为属性增加特性
[NotValue("123")]
public string Value
{
    get { return _value; }
    set { _value = value; }
}

[NotValue("234")]
public string MyVar
{
    get { return _myVar; }
    set { _myVar = value; }
}

WPF绑定(Binding)下的数据验证IDataErrorInfo
上面的这种写法可以简化验证所需要的代码,而且有很强的可读性和可维护性,如果直接把自定义的特性直接加到类上,使得该类中所有的属性都应用验证规则可以修改苏索引器,在上面所写的代码中加上

NotValueAttribute? classAttr =(NotValueAttribute?)this.GetType().GetCustomAttribute(typeof(NotValueAttribute), false);
if (classAttr !=null)
{
    PropertyInfo? classPInfo = this.GetType().GetProperty(columnName, BindingFlags.Public | BindingFlags.Instance);
    if (classPInfo.GetValue(this)==null) { return string.Empty; }
    else if (classPInfo.GetValue(this).ToString() == classAttr.ValidateValue)
    {
        return "字段不能为" + classAttr.ValidateValue;
    }
}

将自定义特性应用在类上

[NotValue("123")]
public class Data : IDataErrorInfo

WPF绑定(Binding)下的数据验证IDataErrorInfo

案例:实现VS新建项目界面

WPF绑定(Binding)下的数据验证IDataErrorInfo

  1. 创建一个继承自IDataErrorInfo的类
public class Data : IDataErrorInfo
{
    public string this[string columnName]
    {
        get
        {
            var pi = this.GetType().GetProperty(columnName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
            if (pi.IsDefined(typeof(RequiredAttribute), false)
                &&
                (pi.GetValue(this) == null || string.IsNullOrEmpty(pi.GetValue(this).ToString()))
                )
                return "字段为空了~~~[IDataErrorInfo]";


            return "";
        }
    }

    public string Error => null;


    private string _projectName = "新建项目";
    [Required]
    public string ProjectName
    {
        get { return _projectName; }
        set
        {
            _projectName = value;
        }
    }

    private string _solutionName = "新建项目";

    [Required]
    public string SolutionName
    {
        get { return _solutionName; }
        set { _solutionName = value; }
    }

}
  1. XAML代码
<Window.DataContext>
        <local:Data/>
    </Window.DataContext>
<Window.Resources>
        <Style TargetType="TextBlock" >
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="FontSize" Value="12"/>
        </Style>
        <!--Validation.ErrorTemplate固定写法-->
        <ControlTemplate x:Key="TextBoxErrorTemplate">
            <AdornedElementPlaceholder/>
        </ControlTemplate>

        <Style TargetType="TextBox">
            <Setter Property="Margin" Value="0,5"/>
            <Setter Property="Width" Value="500"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="VerticalContentAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TextBox}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition MinHeight="30"/>
                                <RowDefinition Height="auto"/>
                            </Grid.RowDefinitions>
                            <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" 
                                    BorderThickness="{TemplateBinding BorderThickness}" 
                                    Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                                <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"
                          VerticalContentAlignment="Center" BorderThickness="0"/>
                            </Border>

                            <TextBlock Text="{Binding Path=(Validation.Errors)[0].ErrorContent,
                                RelativeSource={RelativeSource Mode=TemplatedParent},StringFormat=* {0}}"
                                       Grid.Row="1" Foreground="Red" Margin="0,3" FontSize="12" Visibility="Collapsed"
                                       Name="errorTxt"/>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="Validation.HasError" Value="True">
                                <Setter Property="BorderBrush" Value="Red" TargetName="border"/>
                                <Setter Property="Visibility" Value="Visible" TargetName="errorTxt"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <!--必须设置,不然整个Template会有一个整体的边框-->
            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource TextBoxErrorTemplate}"/>
        </Style>

        <Style TargetType="ComboBox">
            <Setter Property="Height" Value="30"/>
            <Setter Property="Margin" Value="0,5"/>
            <Setter Property="Width" Value="500"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
        </Style>
        <Style TargetType="Button">
            <Setter Property="Height" Value="28"/>
            <Setter Property="Width" Value="80"/>
            <Setter Property="Margin" Value="5,0"/>
        </Style>
    </Window.Resources>
<Grid Margin="30">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="28"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="28"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="28"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="28"/>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="28"/>
            <RowDefinition/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <TextBlock Text="配置新项目" FontSize="22"/>
        <TextBlock Text="WPF应用程序" Grid.Row="1" FontSize="16" Margin="0,15"/>
        <TextBlock Text="项目名称" Grid.Row="2"/>
        <TextBox Grid.Row="3" Text="{Binding ProjectName,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"/>
        <TextBlock Text="位置" Grid.Row="4"/>
        <ComboBox Grid.Row="5"/>
        <TextBlock Text="解决方案" Grid.Row="6"/>
        <ComboBox Grid.Row="7"/>
        <TextBlock Text="解决方案名称" Grid.Row="8"/>
        <TextBox Grid.Row="9" Text="{Binding SolutionName,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}"/>
        <CheckBox Content="将解决方案和项目放在同一个目录中" Grid.Row="10"
                  VerticalAlignment="Center"/>
        <StackPanel Orientation="Horizontal" Grid.Row="12" HorizontalAlignment="Right">
            <Button Content="上一步"/>
            <Button Content="下一步"/>
        </StackPanel>
    </Grid>

关注点要设置Validation.ErrorTemplate,不然整个Template会有一个整体的边框
WPF绑定(Binding)下的数据验证IDataErrorInfo文章来源地址https://www.toymoban.com/news/detail-414140.html

到了这里,关于WPF绑定(Binding)下的数据验证IDataErrorInfo的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • WPF入门第六篇 WPF的Binding

    在传统的Windows软件中,大部分都是UI驱动程序的模式,也可以说事件驱动程序。WPF作为Winform的升级,它把UI驱动程序彻底改变了,核心回到了数据驱动程序的模式上面,这样,程序就回到了算法和数据。数据,才是真正需要重点处理的。 Binding最为重要的一个特点是通讯,连

    2023年04月08日
    浏览(42)
  • C# WPF数据绑定方法以及重写数据模板后数据绑定

    写在前面 本文将会介绍WPF如何 实现前后端数据绑定 和在进行 数据绑定时常用的方法和类 以及对于DataGrid、ListView这样的控件 重写数据模板后控件如何进行数据绑定 。 本文主要针对于数据绑定的基础实现进行介绍,通过此博文你将会有能力编写一个MVVM设计模式的C#、WPF项目

    2023年04月17日
    浏览(45)
  • [ue4] 着色器绑定(Shader Binding)

            当我们在ue4中制作了一个美术材质之后,引擎本身会为我们做很多事情,它会把结点翻译为hlsl,生成多个shader变体,并在多个mesh pass中去选择性的调用所需的shader,其中一个重要的过程就是获取shader绑定的数据。         本文将主要讨论ue4是如何处理来自材质的不

    2024年02月10日
    浏览(47)
  • WPF数据绑定

    数据绑定是一种历经时间考验的传统方式,做法是从对象中提取信息,并在应用程序的用户界面中显示提取的信息,不用编写枯燥的代码就可以完成所有工作。富客户端通常使用双向绑定,这种数据绑定提供了从用户界面向一些对象推出信息的能力——同样,不需要或者几乎

    2024年02月11日
    浏览(42)
  • C# WPF 数据绑定

    后台变量发生改变,前端对应的相关属性值也发生改变 接口 INotifyPropertyChanged 用于通知客户端(通常绑定客户端)属性值已更改。 官方示例代码如下 示例演示 before after 本示例提供了多种绑定方式,使用接口进行绑定,不使用接口进行绑定 1.在MainWindow中进行属性更改 2.在

    2024年02月02日
    浏览(44)
  • WPF 入门笔记 - 04 - 数据绑定

    慢慢来,谁还没有一个努力的过程。 --网易云音乐 数据绑定概述 (WPF .NET) 什么是数据绑定? 数据绑定(Data Binding)是 WPF 一种强大的机制,用于在应用程序的各个部分之间建立数据的双向关联。它允许你将数据从一个源(例如对象、集合、数据库等)绑定到目标控件的属性,

    2024年02月09日
    浏览(63)
  • WPF 数据绑定类属性 和数据更新

    WPF中数据绑定是一个非常强大的功能,不仅可以绑定后台数据,还可以进行实时更新。 在后台创建模型类,然后在标签页面进行导入并绑定。 // 实现数据更新需要再模型类里面添加INotifyPropertyChanged接口 // INotifyPropertyChanged 检查属性是否发生变化的接口 此方法在模型类数据变

    2024年04月15日
    浏览(41)
  • 记一次WPF的DataGrid绑定数据

    之前一直在用winform,但是感觉界面不好看,然后就自己在网上学习WPF。一开始看到DataGrid的时候,还以为它是DataGridView,然后用winform的方法绑定数据发现不行,在不断的查找之后,终于学会了怎么简单的绑定数据。 工具:VStudio2022 框架:.net framework 4.8 新建一个 WPF 窗体,再

    2024年03月28日
    浏览(50)
  • WPF --- 如何以Binding方式隐藏DataGrid列

    如题,如何以Binding的方式动态隐藏DataGrid列? 像这样: 先在ViewModel创建数据源 People 和控制列隐藏的 IsVisibility ,这里直接以 MainWindow 为 DataContext 然后创建 VisibilityConverter ,将布尔值转化为 Visibility 。 然后再界面绑定 IsVisibility ,且使用转化器转化为 Visibility ,最后增加一个

    2024年02月05日
    浏览(64)
  • WPF 入门笔记 - 04 - 数据绑定 - 补充内容:资源基础

    宇宙很大,生活更大,也许以后还有缘相见。 --三体 🌌 💭 该篇作为[WPF 入门笔记 - 04 - 数据绑定] - Additional Content 章节的补充内容 XAML 资源概述 (WPF .NET) WPF中的每一个元素都有一个 Resources 属性,该属性存储了一个资源字典集合。一般来说,可以把WPF的资源按照不同的性质分

    2024年02月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包