4.Binding类之转化器和验证规则

  • 4.Binding类之转化器和验证规则已关闭评论
  • 122 次浏览
  • A+
所属分类:.NET技术
摘要

转化器 IValueConverter接口 Binding类还有一个Converter属性,其实,它是一个IValueConverter接口。它的主要作用是:前后端建立绑定时,定义一套自定义逻辑,让前端显示的数据与后端获取的数据建立一定的对应关系。

转化器

IValueConverter接口

Binding类还有一个Converter属性,其实,它是一个IValueConverter接口。它的主要作用是:前后端建立绑定时,定义一套自定义逻辑,让前端显示的数据与后端获取的数据建立一定的对应关系。

比如Person对象有一个年龄(Age)属性,我们在前端显示某个人的年龄时,可以根据不同的年龄,显示不同的背景颜色。这个时候,实际上是根据这个输入的整型数据返回一个不同颜色的画刷。

    //     // 摘要:     //     Provides a way to apply custom logic to a binding.     public interface IValueConverter     {         object Convert(object value, Type targetType, object parameter, CultureInfo culture);                  object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);     }

 

IValueConverter接口有两个方法成员,分别是Convert和ConvertBack。

Convert方法成员:输入的value及parameter参数,根据自定义逻辑判断,返回一个object对象给前端XAML使用。

ConvertBack方法成员:与Convert相反,将前端输入的数据转换成另一个对象返回给后端的数据源。

IValueConverter示例

public class AgeToColorConverter : IValueConverter {     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)     {         SolidColorBrush background = Brushes.Black;           if (value != null && int.TryParse(value.ToString(), out int age))         {             if (age < 20)             {                 background = Brushes.Green;             }             else if (age < 40)             {                 background = Brushes.Blue;             }             else if (age < 60)             {                 background = Brushes.Orange;             }             else if (age < 80)             {                 background = Brushes.Red;             }             else if (age < 90)             {                 background = Brushes.Purple;             }             else             {                 background = Brushes.Gray;             }         }           return background;     }       public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)     {         throw new NotImplementedException();     } }

然后在XAML前端对转换器进行实例化

<Window.Resources>     <local:AgeToColorConverter x:Key="AgeToColorConverter"/> </Window.Resources>

我们就可以使用这个Key名叫AgeToColorConverter的实例。

Background="{Binding Person.Age,Converter={StaticResource AgeToColorConverter}}"

 

IMultiValueConverter接口

与IValueConverter类似的,还有一个叫IMultiValueConverter——多值转换器。它的定义和IValueConverter也十分类似。

public interface IMultiValueConverter {     object Convert(object[] values, Type targetType, object parameter, CultureInfo culture);     object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture);   }

Convert第一个参数变成了values,表示它可以传入多个值。

IMultiValueConverter示例

/// <summary>  /// 多值转换器  /// </summary>  public class MultiColorConverter : IMultiValueConverter  {      public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)      {          if (values != null && values.Length == 2)          {              var age_result = int.TryParse(values[0].ToString(), out int age);              var money_result = int.TryParse(values[1].ToString(), out int money);              if(age_result&& money_result)              {                  if (age < 30 && money > 50000)                  {                      return "年纪轻轻的有钱人";                  }                  else if (age >= 30 && age <= 60 && money < 5000)                  {                      return "悲催的中年人";                  }                  else if (age < 30 && money < 5000)                  {                      return "这个年轻人没什么钱";                  }                  else if (age >= 30 && money > 90000)                  {                      return "富豪";                  }                  else                  {                      return "一个平凡的人";                  }              }                        }          return null;      }        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)      {          throw new NotImplementedException();      }  }

如上所示,我们定义了一个多值转换器,values参数传入了两个元素,分别是年龄和金钱。这里为什么能确定是两个元素?因为我们在前端使用这个转换器时,明确的传入了两个值。

xaml前端页面使用:

<TextBlock Margin="5" >     <Run Text="称号:"/>     <Run>         <Run.Text>             <MultiBinding Converter="{StaticResource MultiColorConverter}">                 <Binding Path="Person.Age" />                 <Binding Path="Person.Money"/>             </MultiBinding>         </Run.Text>     </Run>                     </TextBlock>

这里需要着重的讲解一下多值转换器在前端的使用。MultiBinding和IMultiValueConverter通常是配套使用的。MultiBinding表示多路绑定的意思,和Binding的用法类似,只是多了一个Bindings集合——表示拥有多个绑定源。

 

验证规则

ValidationRule是一个抽象类,提供创建自定义规则的一个方式,旨在检查用户输入的有效性。所以,我们要验证前端输入的各项数据的有效性时,需要自己定义各自的验证规则。

在数据绑定时,Binding类有一个ValidationRules属性,这个属性专门用来存放开发者自定义的验证规则。

例如,我们假定用户名的长度必须在1-10个字符之间,且用户的年龄在1-100之前,那么就可以围绕这两个条件自定义两个不同的验证规则,它们定义如下:

用户名验证规则:

public class NameValidationRule : ValidationRule {     public override ValidationResult Validate(object value, CultureInfo cultureInfo)     {         if (value != null && value.ToString().Length > 1 && value.ToString().Length <= 10)         {             return new ValidationResult(true, "通过");         }           return new ValidationResult(false, "用户名长度1-10个字符");     } }

年龄验证规则:

public class AgeValidationRule : ValidationRule {     public override ValidationResult Validate(object value, CultureInfo cultureInfo)     {         double myValue = 0;         if (double.TryParse(value.ToString(), out myValue))         {             if (myValue >= 1 && myValue <= 100)             {                 return new ValidationResult(true, null);             }         }           return new ValidationResult(false, "请输入 1 至 100的年龄");     } }

在XAML前端代码中,TextBox输入框分别绑定了用户名和年龄,它们在绑定时如何调用验证规则呢?

<StackPanel Orientation="Horizontal">     <TextBlock Text="姓名:" Margin="5"/>     <TextBox Width="145" Height="25">         <TextBox.Text>             <Binding Path="Person.Name" UpdateSourceTrigger="PropertyChanged">                 <Binding.ValidationRules>                     <local:NameValidationRule ValidatesOnTargetUpdated="True" />                 </Binding.ValidationRules>             </Binding>         </TextBox.Text>         <Validation.ErrorTemplate>             <ControlTemplate>                 <DockPanel>                     <Grid DockPanel.Dock="Right" Width="auto" Height="auto" VerticalAlignment="Center" Margin="3 0 0 0">                         <TextBlock Width="auto" Height="auto" Foreground="Red"                                  Text="{Binding ElementName=AdornedElementPlaceholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>                     </Grid>                     <Border BorderBrush="Red" BorderThickness="0" CornerRadius="2">                         <AdornedElementPlaceholder x:Name="AdornedElementPlaceholder"/>                     </Border>                 </DockPanel>             </ControlTemplate>         </Validation.ErrorTemplate>     </TextBox> </StackPanel> <StackPanel Orientation="Horizontal">     <TextBlock Text="年龄:" Margin="5"/>     <TextBox Width="145" Height="25">         <TextBox.Text>             <Binding Path="Person.Age" UpdateSourceTrigger="PropertyChanged">                 <Binding.ValidationRules>                     <local:AgeValidationRule ValidatesOnTargetUpdated="True" />                 </Binding.ValidationRules>             </Binding>         </TextBox.Text>         <Validation.ErrorTemplate>             <ControlTemplate>                 <DockPanel>                     <Grid DockPanel.Dock="Right" Width="auto" Height="auto" VerticalAlignment="Center" Margin="3 0 0 0">                         <TextBlock Width="auto" Height="auto" Foreground="Red"                                  Text="{Binding ElementName=AdornedElementPlaceholder, Path=AdornedElement.(Validation.Errors).CurrentItem.ErrorContent}"/>                     </Grid>                     <Border BorderBrush="Red" BorderThickness="0" CornerRadius="2">                         <AdornedElementPlaceholder x:Name="AdornedElementPlaceholder"/>                     </Border>                 </DockPanel>             </ControlTemplate>         </Validation.ErrorTemplate>     </TextBox> </StackPanel>

ValidationRule会把验证结果保存在AdornedElementPlaceholder的AdornedElement属性中,所以,需要利用绑定的方法去绑定下面这个路径。