WPF表单验证

利用Validator.TryValidateProperty方法以及IDataErrorInfo实现

XML代码如下 

复制代码
<Grid>
    <Slider VerticalAlignment="Bottom" Minimum="0" Maximum="1000" Name="slider" Value="10"></Slider>
    <TextBox Height="30" Width="150"  Name="tex"  Validation.ErrorTemplate="{StaticResource ErrorTemplate}">
        <!--Validation.Error="tbx1_Error"-->
        <TextBox.Text>
            <Binding ElementName="slider" Path="Value" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True">
                <Binding.ValidationRules>
                    <local:CustomValidationRule ValidatesOnTargetUpdated="True"/>
                </Binding.ValidationRules>
            </Binding>
        </TextBox.Text>

    </TextBox>
    <TextBox Height="30" Width="150" Margin="0,100,0,0">
        <i:Interaction.Behaviors>
            <local:TextBoxWatermarkBehavior Watermark="11111"/>
        </i:Interaction.Behaviors>
    </TextBox>
</Grid>
复制代码

样式如下

复制代码
  <ControlTemplate x:Key="ErrorTemplate">
      <DockPanel>
          <TextBlock DockPanel.Dock="Bottom"
                 Foreground="Red"
                 FontSize="10"
                 Text="{Binding ElementName=adornedElementName, 
                                  Path=AdornedElement.(Validation.Errors)[0].ErrorContent}" 
                     Width="{TemplateBinding Width}" Height="{TemplateBinding Height}"/>
          <Border BorderBrush="Red" BorderThickness="0.5">
              <AdornedElementPlaceholder Name="adornedElementName"/>
          </Border>
          <!--<Border BorderBrush="Red" BorderThickness="1">
              <AdornedElementPlaceholder Name="adornedElementName">
                  
              </AdornedElementPlaceholder>
          </Border>-->
      </DockPanel>
  </ControlTemplate>
复制代码

C#代码

复制代码
 public class ValidateModelBase:NotifyBase, IDataErrorInfo
 {

     public ValidateModelBase()
     {

     }

     #region 属性 
     /// <summary>
     /// 表当验证错误集合
     /// </summary>
     public Dictionary<string, string> dataErrors = new Dictionary<string, string>();

     /// <summary>
     /// 是否验证通过
     /// </summary>
     public bool IsValidated
     {
         get
         {
             if (dataErrors != null && dataErrors.Count > 0)
             {
                 return false;
             }
             return true;
         }
     }
     #endregion

     public string this[string columnName]
     {
         get
         {
             ValidationContext vc = new ValidationContext(this, null, null);
             vc.MemberName = columnName;
             var res = new List<System.ComponentModel.DataAnnotations.ValidationResult>();
             var result = Validator.TryValidateProperty(this.GetType().GetProperty(columnName).GetValue(this, null), vc, res);
             if (res.Count > 0)
             {
                 string errorInfo = string.Join(Environment.NewLine, res.Select(r => r.ErrorMessage).ToArray());
                 AddDic(dataErrors, columnName, errorInfo);
                 return errorInfo;
             }
             RemoveDic(dataErrors, columnName);
             return null;
         }
     }

     public string Error
     {
         get
         {
             return null;
         }
     }


     #region 附属方法
     /// <summary>
     /// 移除字典
     /// </summary>
     /// <param name="dics"></param>
     /// <param name="dicKey"></param>
     private void RemoveDic(Dictionary<string, string> dics, string dicKey)
     {
         dics.Remove(dicKey);
     }

     /// <summary>
     /// 添加字典
     /// </summary>
     /// <param name="dics"></param>
     /// <param name="dicKey"></param>
     private void AddDic(Dictionary<string, string> dics, string dicKey, string dicValue)
     {
         if (!dics.ContainsKey(dicKey)) dics.Add(dicKey, dicValue);
     }
     #endregion

 }
复制代码

NotifyBase如下实现INotifyPropertyChanged接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class NotifyBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
 
      public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
        }
 
 
        remove
        {
            CommandManager.RequerySuggested -= value;
        }
    }
 
    public void SetProperty<T>(ref T feild, T value, [CallerMemberName] string propName = "")
    {
        feild = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
    }
}

  UserModel实体类如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class UserModel : ValidateModelBase
{
    private string userName;
    [Required(ErrorMessage = "用户名不可为空")]
    public string UserName
    {
        get { return userName; }
        set { userName = value; SetProperty(ref userName,value); }
    }
 
    private string userAge;
    [Required(ErrorMessage = "年龄不可为空")]
    [Range(0, 100, ErrorMessage = "年龄范围为0~100")]
    public string UserAge
    {
        get { return userAge; }
        set { userAge = value; SetProperty(ref userAge, value); }
    }
 
    private bool isFormValid;
 
    public bool IsFormValid
    {
        get { return isFormValid; }
        set { isFormValid = value; SetProperty(ref isFormValid, value); }
    }
}

  

posted @   ¥东方不败  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示