WPF验证与异常

ValidationRules

ExceptionValidationRule

XAML代码:

 <TextBox Name="tb2">
     <TextBox.Text>
         <Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
             <Binding.ValidationRules>
                 <ExceptionValidationRule />
             </Binding.ValidationRules>
         </Binding>
     </TextBox.Text>
 </TextBox>
 <!--捕获到框架自带的异常-->
 <TextBlock Text="{Binding ElementName=tb2,Path=(Validation.Errors)[0].ErrorContent}" Foreground="Red"/>

显示结果:

注意:如果写ExceptionValidationRule的时候,报错是英文的,如果没有写,报错是中文的,都会有报错捕捉。都会有验证错误,因为咱这里的值是int类型,系统也会捕捉到,所以看个人所需

使用事件进行捕捉:

方法:Validation.GetHasError() 是否有报错

Validation.GetErrors() 获得报错信息

属性:ErrorContent 报错信息

private void Button_Click(object sender, RoutedEventArgs e)
{
    // 是否有报错
    if (Validation.GetHasError(this.tb1))
    {
        // 获取报错
        var errors = Validation.GetErrors(this.tb1);
        var errStr = errors[0].ErrorContent;
    }
    // 是否有报错
    if (Validation.GetHasError(this.tb2))
    {
        // 获取报错
        var errors = Validation.GetErrors(this.tb2);
        var errStr = errors[0].ErrorContent;
    }
}
自定义ValidationRule

继承ValidationRule,并重写方法 Validate

C#代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace XH.BindingLesson.DataValidation
{
    // 实际的调用实际 是在界面上的控件被绑定的属性发生变化的时候
    // 继承 ValidationRule
    public class ValueValidation : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            // 做值的校验规则 

            // value参数指的是目标值

            if(int.TryParse(value.ToString(), out int v))
            {
                if (v == 123)
                    return new ValidationResult(false, "值不可以为123");
            }
            else
                return new ValidationResult(false, "输入信息不是数值");
            return new ValidationResult(true,null);
        }
    }
}

XAML使用:

 <TextBox Name="tb3">
     <TextBox.Text>
         <Binding Path="Value" UpdateSourceTrigger="PropertyChanged">
             <Binding.ValidationRules>
                 <local:ValueValidation />
             </Binding.ValidationRules>
         </Binding>
     </TextBox.Text>
 </TextBox>
 <TextBlock Text="{Binding ElementName=tb3,Path=(Validation.Errors)[0].ErrorContent}" Foreground="Red"/>

效果显示:

IDataErrorInfo

需要继承IDataErrorInfo接口,然后完成两个方法

public class DataBase : IDataErrorInfo
{
  public string Error { get; set; }
  // 索引 获取某一列的值
  public string this[string columnName] => throw new NotImplementedException();
}

在外面可以根据类名[列名]调用第二个方法:类似string[0]

每次,属性值更新时候,会调用这个方法:

xaml代码:

ValidatesOnDataErrors 打开类中的IDataErrorInfo的属性验证,如果不开,不用调用以上方法

<TextBox Name="tb4" 
  Text="{Binding Value,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" />
<TextBox Name="tb5" 
  Text="{Binding MyProperty,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" />
<TextBox Name="tb6" 
  Text="{Binding MyProperty1,UpdateSourceTrigger=PropertyChanged,ValidatesOnDataErrors=True}" />
<TextBlock Text="{Binding ElementName=tb4,Path=(Validation.Errors)[0].ErrorContent}" 
  Foreground="Red"/>
<TextBlock Text="{Binding ElementName=tb5,Path=(Validation.Errors)[0].ErrorContent}"
  Foreground="Red"/>
<TextBlock Text="{Binding ElementName=tb6,Path=(Validation.Errors)[0].ErrorContent}"
  Foreground="Red"/>

写法一:

可以根据每一列的值,进行单独判断

public string this[string columnName]
{
    get
    {
        if (columnName == "Value" && this.Value >1000)
        {
            return "Value 值大于 1000!!!【IDataErrorInfo】";
        }
        if (columnName == "MyProperty" && this.MyProperty.Length > 50)
        {
            return "MyProperty 长度大于 50!!!【IDataErrorInfo】";
        }
        return "";
    }
}

写法二:

利用反射,根据特性来判断:

在字段上方写特性 可以根据特性反射判断

[MaxLength(100)]
[Url] // 判断url是否合法
[EmailAddress(ErrorMessage = "邮箱地址不正确")] // 邮箱地址
[CheckRepeat(ErrorMessage = "输入信息有误")]
[IPCheck(ErrorMessage ="IP不对")]
public string MyProperty1 { get; set; } = "";

public string this[string columnName]
 {
     get
     {
         // 使用反射
         PropertyInfo pi = this.GetType().GetProperty(columnName);

         // 检查当前属性是否添加了指定的特性
         // IsDefined 判断是否有特性
         if (pi.IsDefined(typeof(MaxLengthAttribute)))
         {
             // 获取当前属性上指定的特定示例 一般是需要获取特性示例中某些值的时候使用
             MaxLengthAttribute ma = (MaxLengthAttribute)pi.GetCustomAttribute(typeof(MaxLengthAttribute));
             string value = pi.GetValue(this).ToString();
             if (value.Length > ma.Length)
             {
                 //return $"{pi.Name} 长度大于 {ma.Length}!!!【IDataErrorInfo】";
                 return ma.ErrorMessage;
             }
         }

         return "";
     }
 }

正则表达式

自定义特性:

需要继承:ValidationAttribute 或者Attribute

建议继承ValidationAttribute 可以直接重写验证方法

using System.ComponentModel.DataAnnotations;
using System.Text.RegularExpressions;

namespace XH.BindingLesson
{
    public class IPCheckAttribute : ValidationAttribute
    {
        public override bool IsValid(object? value)
        {
            // 检查IP格式
            // 正则表达式
            // 核心:字符串中每个字符逐个判断

            // 192.168.1.2
            // 使用.间隔
            // 每个间隔的数字都是0-255
            // \.  \d
            string patternIpv4 = @"\b(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\b";

            return Regex.IsMatch(value.ToString(), patternIpv4);

            //return base.IsValid(value);
        }
    }
}

在需要验证的类中,字段中,写入以下:

[IPCheck(ErrorMessage ="IP不对")]
public string MyProperty1 { get; set; } = "";

 public string this[string columnName]
 {
     get
     {
         // 自定义检验IP
         if (pi.IsDefined(typeof(IPCheckAttribute)))
         {
             IPCheckAttribute ia = pi.GetCustomAttribute<IPCheckAttribute>();
             if (!ia.IsValid(pi.GetValue(this)))
             {
                 return ia.ErrorMessage;
             }
         }
         return "";
     }
 }

显示结果如下:

扩展:把报错写在TextBox模板中

xaml代码:模板代码:

<Window.Resources>
  <Style TargetType="TextBox">
    <Setter Property="Margin" Value="3" />
    <Setter Property="Height" Value="35" />
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="TextBox">
          <Border BorderBrush="{TemplateBinding BorderBrush}" 
            Background="{TemplateBinding Background}"
            BorderThickness="{TemplateBinding BorderThickness}"
            CornerRadius="5">
            <Grid>
              <ScrollViewer Name="PART_ContentHost" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"/>
              <!--主要是这个,可以显示报错信息-->
              <TextBlock  Text="{Binding Path=(Validation.Errors)[0].ErrorContent,RelativeSource={RelativeSource Mode=TemplatedParent}}"
                          HorizontalAlignment="Right" 
                          Name="error"
                          Visibility="Collapsed"
                          Foreground="Red"/>
            </Grid>
          </Border>
          <ControlTemplate.Triggers>
            <!--哪个控件使用,就是哪个控件的报错信息-->
            <Trigger Property="Validation.HasError" Value="True">
              <Setter TargetName="error" Property="Visibility" Value="Visible" />
            </Trigger>
          </ControlTemplate.Triggers>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</Window.Resources>

注意:

1、TextBlock报错的显示绑定方式,

2、触发器的属性 Validation.HasError

显示结果如下:

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF中,可以使用属性验证器来验证文本框是否为空,并防止提交无效数据。以下是一些实现该功能的步骤: 1. 在XAML中设置文本框的属性验证规则,例如: ``` <TextBox Text="{Binding UserName, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}" /> ``` 其中,"UserName"是ViewModel中的属性名,"UpdateSourceTrigger=PropertyChanged"表示在文本框中输入时更新属性值,"ValidatesOnDataErrors=True"表示启用属性验证器。 2. 在ViewModel中实现属性验证器,例如: ``` public string UserName { get { return _userName; } set { if (string.IsNullOrEmpty(value)) { throw new Exception("用户名不能为空!"); } _userName = value; OnPropertyChanged("UserName"); } } ``` 该代码段中,如果属性值为空,则抛出异常。此时,无法提交无效数据,用户需要输入有效值才能提交。 3. 在窗口中添加"Save"按钮,并绑定Command,例如: ``` <Button Content="保存" Command="{Binding SaveCommand}" /> ``` 4. 在ViewModel中实现"Save"命令,例如: ``` public ICommand SaveCommand { get { if (_saveCommand == null) { _saveCommand = new RelayCommand( param => this.CanSave(), param => this.Save()); } return _saveCommand; } } private bool CanSave() { //判断数据是否有效 return !string.IsNullOrEmpty(UserName); } private void Save() { //保存数据 } ``` 该代码段中,"CanSave"方法用于判断数据是否有效,如果用户名为空,则无法保存;"Save"方法用于保存数据。 综上所述,当文本框为空时,属性验证器会抛出异常,无法提交无效数据。用户需要输入有效值才能提交。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值