| 1、ValidationRule 驗(yàn)證ValidationRule:是通過(guò)ValidationRule中的的Validate方法來(lái)驗(yàn)證我們綁定的屬性。所以我們的用法是繼承ValidationRule,重寫他的Validate方法。示例 public class RequiredRule : ValidationRule
    {
        public override ValidationResult Validate(object value, CultureInfo cultureInfo)
        {
            if (value == null)
                return new ValidationResult(false, "不能為空值!");
            if (string.IsNullOrEmpty(value.ToString()))
                return new ValidationResult(false, "不能為空字符串!");
            return new ValidationResult(true, null);
        }
    }而XAML中需要把錯(cuò)誤信息顯示出來(lái)。 <Window.Resources>
        <ControlTemplate x:Key="ErrorTemplate">
            <Border BorderBrush="Red" BorderThickness="1">
                <AdornedElementPlaceholder/>
            </Border>
        </ControlTemplate>
        <Style TargetType="TextBox">
            <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ErrorTemplate}">
            </Setter>
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="True">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <StackPanel>
        <TextBlock Text="姓名"/>
        <TextBox>
            <TextBox.Text>
                <Binding Path="Name" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                    <Binding.ValidationRules>
                        <ValidationRules:RequiredRule/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
        <TextBlock Text="年齡"/>
        <TextBox >
            <TextBox.Text>
                <Binding Path="Age" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True">
                    <Binding.ValidationRules>
                        <ValidationRules:GreaterThanRule Number="10"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>這樣顯示的錯(cuò)誤信息就會(huì)以 ToolTip和紅色邊框的形式顯示出來(lái)。但這邊如果又在TextBox里面設(shè)置ToolTip那么就會(huì)優(yōu)先選擇TextBox里的,也就是Style中的ToolTip遇到錯(cuò)誤信息是不會(huì)顯示出來(lái)的,而是顯示TextBox中的ToolTip。所以我們可以改善一下顯示的模版來(lái)解決這個(gè)問(wèn)題。 <ControlTemplate x:Key="ErrorTemplate">
            <DockPanel LastChildFill="true">
                <Border Background="Red" DockPanel.Dock="right" Margin="5,0,0,0" Width="20" Height="20" CornerRadius="10"
                            ToolTip="{Binding ElementName=customAdorner, Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
                    <TextBlock Text="!" VerticalAlignment="center" HorizontalAlignment="center" FontWeight="Bold" Foreground="white">
                    </TextBlock>
                </Border>
                <AdornedElementPlaceholder Name="customAdorner" VerticalAlignment="Center" >
                    <Border BorderBrush="red" BorderThickness="1" />
                </AdornedElementPlaceholder>
            </DockPanel>
        </ControlTemplate>2、Exception 驗(yàn)證Exception :我們xaml中綁定的對(duì)象是屬性。所以Exception驗(yàn)證,就是通過(guò)屬性的改變來(lái)判斷是否正常。如:  public int Age
        {
            get { return _age; }
            set
            {
                if (value > 200)
                {
                    throw new Exception("年齡不能大于200");
                }
                _age = value;
            }
        }同樣跑出的異常在Xaml中也要顯示下。XAML同上。這種方式就會(huì)破壞POCO的設(shè)計(jì)原則。 3、IDataErrorInfo 驗(yàn)證IDataErrorInfo:這個(gè)驗(yàn)證是通過(guò)我們的實(shí)體對(duì)象繼承IDataErrorInfo來(lái)實(shí)現(xiàn)的。這里聲明的this索引器來(lái)訪問(wèn)類的成員。  public class BaseDataErrorInfo : IDataErrorInfo
    {
        private string _error;
        public string this[string columnName]
        {
            get { return GetErrorFor(columnName); }
        }
        public string Error
        {
            get { return _error; }
            set { _error = value; }
        }
        public virtual string GetErrorFor(string columnName)
        {
            return string.Empty;
        }
    }public class Person : BaseDataErrorInfo
    {
        public string Name { get; set; }
        public override string GetErrorFor(string columnName)
        {
            if (columnName == "Name")
                if (string.IsNullOrEmpty(Name))
                    return "Name 不能為空";
            return base.GetErrorFor(columnName);
        }
    }XAML同上。 4、Custom Control 驗(yàn)證這里我即不想污染實(shí)體類,又想實(shí)現(xiàn)一個(gè)通用的Validate。我想通過(guò)我xaml綁定的屬性和它所屬的控件。來(lái)顯示ToolTip。   public abstract class Validator : FrameworkElement
    {
        static Validator()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(Validator), new FrameworkPropertyMetadata(typeof(Validator)));
        }
        public virtual string ErrorMessage { get { return string.Empty; } }
        public abstract bool InitialValidation();
        public FrameworkElement ElementName
        {
            get { return (FrameworkElement)GetValue(ElementNameProperty); }
            set { SetValue(ElementNameProperty, value); }
        }
        // Using a DependencyProperty as the backing store for ElementName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ElementNameProperty =
            DependencyProperty.Register("ElementName", typeof(FrameworkElement), typeof(Validator), new PropertyMetadata(null));
        public object Source
        {
            get { return (object)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }
        // Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(object), typeof(Validator), new UIPropertyMetadata(new PropertyChangedCallback(ValidPropertyPropertyChanged)));
        private static void ValidPropertyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var validator = d as Validator;
            if (validator != null)
                validator.SetSourceFromProperty();
            if (string.IsNullOrEmpty(e.NewValue.ToString()))
            {
                if (validator != null)
                {
                    validator.IsValid = validator.InitialValidation();
                    if (validator.ElementName.DataContext != null)
                        validator.ShowToolTip();
                    validator.IsValid = false;
                }
            }
        }
        private void ShowToolTip()
        {
            if (IsValid)
            {
                timer = new DispatcherTimer();
                timer.Interval = TimeSpan.FromSeconds(1.5);
                _toolTip = new ToolTip();
                _toolTip.StaysOpen = true;
                _toolTip.PlacementTarget = ElementName;
                _toolTip.Placement = PlacementMode.Right;
                _toolTip.Content = ErrorMessage;
                _toolTip.IsOpen = true;
                timer.Tick += (sender, args) =>
                                  {
                                      _toolTip.IsOpen = false;
                                      timer.Stop();
                                  };
                timer.Start();
            }
        }
        private void SetSourceFromProperty()
        {
            var expression = this.GetBindingExpression(SourceProperty);
            if (expression != null && this.ElementName == null)
                this.SetValue(Validator.ElementNameProperty, expression.DataItem as FrameworkElement);
        }
        private ToolTip _toolTip;
        private DispatcherTimer timer;
        public bool IsValid { get; set; }
    }這是一個(gè)簡(jiǎn)單的Validate基類。提供思想。功能不完善。 然后繼承這個(gè)Validator public class RequiredValidator : Validator
    {
        public override string ErrorMessage { get { return "不能為空值"; } }
        public override bool InitialValidation()
        {
            if (Source == null)
                return false;
            return string.IsNullOrEmpty(Source.ToString());
        }
    }這里ErrorMessage是顯示錯(cuò)誤信息。 InitialValidation方法是我們要驗(yàn)證的規(guī)則。 代碼 關(guān)于使用的小例子: 一、通過(guò)代碼實(shí)現(xiàn)數(shù)據(jù)綁定通過(guò)代碼實(shí)現(xiàn)數(shù)據(jù)綁定,使用的是System.Windows.Data命名空間的Binding類,主要使用Binding類的如下的屬性: 
 在綁定目標(biāo)控件上使用SetBinding方法添加數(shù)據(jù)綁定。例如將MyData的Name屬性綁定到txtName控件的Text屬性上,使用MyColorConverter轉(zhuǎn)換器將MyBindingColor的ColorObject屬性綁定到rec控件的Fill屬性上: 1: MyData data = new MyData(); 2: 3: Binding binding1 = new Binding(); 4: binding1.Source = data; 5: binding1.Mode = BindingMode.OneWay;    6: binding1.Path = new PropertyPath("Name");7: 8: txtName.SetBinding(TextBox.TextProperty, binding1); 9: 10: 11: MyBindingColor color = new MyBindingColor(); 12: 13: Binding binding2 = new Binding(); 14: binding2.Source = color; 15: binding2.Mode = BindingMode.OneWay;   16: binding2.Path = new PropertyPath("ColorObject");17: binding2.Converter = new MyColorConverter(); 18: 19: rec.SetBinding(Rectangle.FillProperty, binding2); 二、實(shí)現(xiàn)綁定數(shù)據(jù)的驗(yàn)證:對(duì)于綁定數(shù)據(jù)的驗(yàn)證,系統(tǒng)采用如下的機(jī)制: 
 使用 WPF 數(shù)據(jù)綁定模型可以將 ValidationRules 與 Binding 對(duì)象相關(guān)聯(lián)。當(dāng)綁定目標(biāo)的屬性向綁定源屬性傳遞屬性值時(shí)(僅限TwoWay模式或OneWayToSource模式),執(zhí)行ValidationRule中的Validate方法,實(shí)現(xiàn)對(duì)界面輸入數(shù)據(jù)的驗(yàn)證。 定義驗(yàn)證可以采用以下三種: 
 例如,定義一個(gè)學(xué)生信息類,要求其學(xué)生成績(jī)?cè)?到100間,學(xué)生姓名的長(zhǎng)度在2到10個(gè)字符間: 1: public class StudentInfoWithValidation : IDataErrorInfo    2: {3: #region 構(gòu)造方法 4: public StudentInfoWithValidation()    5:     {6: StudentName = "Tom"; 7: Score = 90; 8: } 9: public StudentInfoWithValidation(string m_StudentName,double m_Score)   10:     {11: StudentName = m_StudentName; 12: Score = m_Score; 13: } 14: #endregion 15: 16: #region 屬性 17: public string StudentName   18:     {19: get; set; 20: } 21: public double Score   22:     {23: get; set; 24: } 25: #endregion 26: 27: #region 實(shí)現(xiàn)IDataErrorInfo接口的成員 28: public string Error   29:     {30: get   31:         {32: return null; 33: } 34: } 35: 36: public string this[string columnName]   37:     {38: get   39:         {40: string result = null; 41: 42: switch (columnName)   43:             {44: case "StudentName": 45: // 設(shè)置StudentName屬性的驗(yàn)證規(guī)則 46: int len = StudentName.Length; 47: if (len < 2 || len > 10)   48:                     {49: result = "StudentName length must between 2 and 10"; 50: } 51: break; 52: case "Score": 53: // 設(shè)置Score屬性的驗(yàn)證規(guī)則 54: if (Score < 0 || Score > 100)   55:                     {56: result = "Score must between 0 and 100"; 57: } 58: break; 59: } 60: 61: return result; 62: } 63: } 64: #endregion 65: } 在界面上,定義兩個(gè)TextBox綁定到StudentName和Score兩個(gè)屬性上,并設(shè)置其采用DataErrorValidationRule: 1: <Window x:Class="WPFDataBindingDemo.WinDataErrorValidationRuleDemo" 2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4: xmlns:local="clr-namespace:WPFDataBindingDemo" 5: Title="WinDataErrorValidationRuleDemo" Height="154" Width="300"> 6: <Canvas Height="116" x:Name="mainCanvas"> 7: <Canvas.Resources> 8: <local:StudentInfoWithValidation x:Key="myData" /> 9: </Canvas.Resources> 10: <Canvas.DataContext>   11:             <Binding Source="{StaticResource myData}" />12: </Canvas.DataContext> 13: <Label Canvas.Left="10" Canvas.Top="10" Height="28" Name="label1" Width="120">StudentName:</Label> 14: <Label Canvas.Left="10" Canvas.Top="36" Height="28" Name="label2" Width="120">Score:</Label> 15: <TextBox Canvas.Left="136" Canvas.Top="12" Height="23" Name="textBox1" Width="120"> 16: <TextBox.Text> 17: <Binding Path="StudentName" 18: Mode="TwoWay" 19: UpdateSourceTrigger="PropertyChanged" 20: ValidatesOnDataErrors="True" /> 21: </TextBox.Text> 22: </TextBox> 23: <TextBox Canvas.Left="136" Canvas.Top="41" Height="23" Name="textBox2" Width="120"> 24: <TextBox.Text> 25: <Binding Path="Score" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"> 26: <!--與上一個(gè)TextBox控件的寫法作用相同--> 27: <Binding.ValidationRules> 28: <DataErrorValidationRule /> 29: </Binding.ValidationRules> 30: </Binding> 31: </TextBox.Text> 32: </TextBox> 33: <Button Canvas.Left="12" Canvas.Top="79" Height="23" Name="button1" Width="118" Click="button1_Click">Get Student Info</Button> 34: <Button Canvas.Left="136" Canvas.Top="79" Height="23" Name="button2" Width="118" Click="button2_Click">Get Validate State</Button> 35: </Canvas> 36: </Window> 
 
 從執(zhí)行的結(jié)果上來(lái)看,當(dāng)驗(yàn)證出現(xiàn)錯(cuò)誤(即索引器屬性返回的字符串不為空時(shí)),系統(tǒng)默認(rèn)給出一種驗(yàn)證錯(cuò)誤的顯示方式(控件以紅色邊框包圍),但是需注意兩點(diǎn): 
 例如上例中,對(duì)于Score對(duì)應(yīng)的TextBox,再加入ExceptionValidationRule: 1: <TextBox Canvas.Left="136" Canvas.Top="41" Height="23" Name="textBox2" Width="120"> 2: <TextBox.Text> 3: <Binding Path="Score" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged"> 4: <!--與上一個(gè)TextBox控件的寫法作用相同--> 5: <Binding.ValidationRules> 6: <DataErrorValidationRule /> 7: <ExceptionValidationRule /> 8: </Binding.ValidationRules> 9: </Binding> 10: </TextBox.Text> 11: </TextBox> 
 
 
 
 
 
 
 
 
 例如,定義一個(gè)類,用來(lái)驗(yàn)證輸入的Email地址是否合法(驗(yàn)證的Email允許為字符串的空值String.Empty,但有輸入必須符合Email的格式要求) 在學(xué)生類中添加Email可讀可寫屬性(并不做相應(yīng)的驗(yàn)證,忽略其他重復(fù)代碼): 1: public string Email    2: {3: set; get; 4: } 定義一個(gè)類,實(shí)現(xiàn)Email格式驗(yàn)證: 1: using System.Globalization; 2: using System.Text.RegularExpressions; 3: using System.Windows.Controls; 4: 5: namespace WPFDataBindingDemo    6: {7: public class EmailValidationRule : ValidationRule    8:     {9: public override ValidationResult Validate(object value, CultureInfo cultureInfo)   10:         {11: bool isValid = false; 12: string message = null; 13: 14: // 檢查輸入值不為空,且是字符串 15: if (value != null && value is string)   16:             {17: string email = value.ToString(); 18: 19: // 檢查輸入的字符串是否為String.Empty 20: if (email != string.Empty)   21:                 {22: string emailFormartRegex =   23:                         @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|" +  24:                         @"(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";25: 26: // 檢查輸入的字符串是否符合Email格式 27: isValid = Regex.IsMatch(email, emailFormartRegex); 28: 29: if (! isValid)   30:                     {31: message = "Input string not match Email Format"; 32: } 33: } 34: else   35:                 {36: // 輸入的字符串為字符串空值時(shí),認(rèn)為驗(yàn)證通過(guò) 37: isValid = true; 38: } 39: } 40: else   41:             {42: message = "Input value is NULL or is not string."; 43: } 44: 45: // 返回驗(yàn)證結(jié)果(ValidationResult對(duì)象) 46: return new ValidationResult(isValid,message); 47: } 48: } 49: } 在界面上: 1: <TextBox Canvas.Left="104" Canvas.Top="70" Height="23" Name="textBox3" Width="152"> 2: <Binding Mode="TwoWay" Path="Email" UpdateSourceTrigger="PropertyChanged"> 3: <Binding.ValidationRules> 4: <local:EmailValidationRule /> 5: </Binding.ValidationRules> 6: </Binding> 7: </TextBox> 
 
 
 
 三、為數(shù)據(jù)驗(yàn)證提供視覺(jué)效果在數(shù)據(jù)驗(yàn)證錯(cuò)誤后,可以通過(guò)以下兩種方式提供相應(yīng)的視覺(jué)效果: 
 如果要使輸入的控件的外觀發(fā)生變化,可以使用Style。例如上例中出錯(cuò),使輸入的文本框的背景顏色和字體顏色發(fā)生變化,并提供ToolTip顯示錯(cuò)誤信息,可以定義如下的Style: 1: <Style TargetType="TextBox"> 2: <Setter Property="Background" Value="White" /> 3: <Setter Property="Foreground" Value="Black" /> 4: <Style.Triggers> 5: <Trigger Property="Validation.HasError" Value="True"> 6: <Setter Property="Background" Value="#DDD" /> 7: <Setter Property="Foreground" Value="Red" /> 8: <Setter Property="ToolTip"    9:                     Value="{Binding RelativeSource={RelativeSource Self},Path=(Validation.Errors)[0].ErrorContent}"/>10: </Trigger> 11: </Style.Triggers> 12: </Style> 效果如下:   
 如果要為相應(yīng)的控件添加一些輔助的控件,可以使用控件模板,如出現(xiàn)驗(yàn)證錯(cuò)誤時(shí),不使用系統(tǒng)默認(rèn)的紅色邊框,而是在文本框后添加一個(gè)紅色的星號(hào): 1: <ControlTemplate x:Key="validErrorTextBoxTemplate"> 2: <DockPanel> 3: <AdornedElementPlaceholder/> 4: <TextBlock Foreground="Red" FontSize="20">*</TextBlock> 5: </DockPanel> 6: </ControlTemplate> 并在每一個(gè)輸入的TextBox中添加:    1: Validation.ErrorTemplate="{StaticResource validErrorTextBoxTemplate}"
 轉(zhuǎn)自:https://www.cnblogs.com/fuchongjundream/p/3844051.html | 
|  |