浅谈WPF之Binding时数据校验和类型转换

  • 浅谈WPF之Binding时数据校验和类型转换已关闭评论
  • 91 次浏览
  • A+
所属分类:.NET技术
摘要

在WPF开发中,Binding实现了数据在Source和Target之间的传递和流通,就像现实生活中的一条条道路,建立起了城镇与城镇之间的衔接,而数据校验和类型转换,就像高速公路之间的收费站和安检站。那在WPF开发中,如何实现数据的校验和类型转换呢?本文以一个简单的小例子,简述在WPF开发中,实现数据校验和类型转换的相关知识点 ,仅供学习分享使用,如有不足之处,还请指正。

在WPF开发中,Binding实现了数据在Source和Target之间的传递和流通,就像现实生活中的一条条道路,建立起了城镇与城镇之间的衔接,而数据校验和类型转换,就像高速公路之间的收费站和安检站。那在WPF开发中,如何实现数据的校验和类型转换呢?本文以一个简单的小例子,简述在WPF开发中,实现数据校验和类型转换的相关知识点,仅供学习分享使用,如有不足之处,还请指正。

浅谈WPF之Binding时数据校验和类型转换

在数据绑定Binding中,数据校验主要通过ValidationRules属性,数据转换主要通过Converter属性

 

数据校验

 

在WPF开发中,校验数据的有效性,主要步骤如下:

 

1. 实现校验规则

 

Binding的ValidationRules是Collection<ValidationRule>类型,是一个校验规则列表,可以支持多重校验。而ValidationRule是一个抽象类,所有要实现业务规则校验,就要继承ValidationRule并实现抽象方法。

ValidationRule的Validate方法返回一个ValidationResult对象,如果校验通过,则ValidationResult的IsValid为true,否则为false。RangeValidationRule主要校验用户输入数据的范围:

using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Controls;  namespace WpfApp4.DataValidate {     public class RangeValidationRule : ValidationRule     {         public override ValidationResult Validate(object value, CultureInfo cultureInfo)         {             double d = 0;             if(double.TryParse(value.ToString(),out d))             {                 if(d>=0 && d <= 100)                 {                     return new ValidationResult(true,null);                 }             }             return new ValidationResult(false, "数据必须在0~100之间");         }     } }

 

2. 设置规则

 

要想应用规则,首先需要引入规则对应的命名空间:xmlns:v="clr-namespace:WpfApp4.DataValidate"

然后设置Binding的ValidationRules规则,如下所示:

<TextBlock Text="年龄" VerticalAlignment="Center"></TextBlock> <TextBox x:Name="tbAge" Width="120" Height="25" Margin="10" Validation.Error="tbAge_Error" VerticalContentAlignment="Center"> 	<TextBox.Text> 		<Binding Path="Age" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True"> 			<Binding.ValidationRules> 				<v:RangeValidationRule ValidatesOnTargetUpdated="True"></v:RangeValidationRule> 			</Binding.ValidationRules> 		</Binding> 	</TextBox.Text> </TextBox> <TextBlock VerticalAlignment="Center" Text="{Binding DataError}" Foreground="Red"></TextBlock>

关于校验规则,有以下几点需要注意:

默认情况下,认为Source的数据总是正确的,规则校验只有当Target更新时,才会生效,因为Target多为用户输入;如果当Source更新时也要生效,则需要配置ValidatesOnTargetUpdated为true。

默认情况下,校验规则返回的错误信息,是不会输出到UI的,如果要输出要UI,需要设置NotifyOnValidationError属性为true。

 

3. 输出校验信息

 

默认情况下,校验信息不会输出到UI,只是显示用户控件为红色边框,如果要输出校验信息,除了设置NotifyOnValidationError属性外,还要订阅Validation.Error事件,并在事件中处理要显示的错误信息,如下所示:

private void tbAge_Error(object sender, ValidationErrorEventArgs e) { 	this.viewModel.ValidationErrorCommand.Execute(e); }

其中上述方法中的命令为ViewModel中定义,如下所示:

public class MainWindowViewModel : ObservableObject { 	private int age;  	public int Age 	{ 		get { return age; } 		set { SetProperty(ref age , value); } 	}  	private string dataError;  	public string DataError 	{ 		get { return dataError; } 		set { SetProperty(ref dataError , value); } 	}   	private TextBox textBox;  	private ICommand winLoadedCommand;  	public ICommand WinLoadedCommand 	{ 		get { 			if (winLoadedCommand == null) 			{ 				winLoadedCommand = new RelayCommand<object>(WinLoaded); 			} 			return winLoadedCommand; } 	}  	private void WinLoaded(object sender) 	{ 		if (sender != null) 		{ 			var win = sender as MainWindow; 			this.textBox = win.tbAge; 		} 	}    	private ICommand validationErrorCommand;  	public ICommand ValidationErrorCommand 	{ 		get { 			if (validationErrorCommand == null) 			{ 				validationErrorCommand = new RelayCommand<object>(DisplayValidationError); 			} 			return validationErrorCommand; } 	}  	private void DisplayValidationError(object obj) 	{ 		if (Validation.GetErrors(this.textBox).Count > 0) 		{ 			this.DataError= Validation.GetErrors(this.textBox)[0].ErrorContent.ToString(); 		} 		else 		{ 			this.DataError = string.Empty; 		} 	}  }

 

4. 数据校验示例演示

 

经过上述步骤,运行程序,如下所示:

浅谈WPF之Binding时数据校验和类型转换

 

数据类型转换

 

在数据绑定时,如果Source端的数据类型和Target端的数据类型不一致时,就需要用到数据类型转换,如:true/false与显示/隐藏之间的转换等,要实现数据转换,需要用到Binding的Converter属性。步骤如下:

 

1. 定义转换器

 

Binding的Converter属性是IValueConverter类型,所以定义转换器需要实现IValueConverter接口,如下所示:

namespace WpfApp4.DataConverter {     public class BoolToVisilityConverter : IValueConverter     {         /// <summary>         /// Source 到 Target         /// </summary>         /// <param name="value"></param>         /// <param name="targetType"></param>         /// <param name="parameter"></param>         /// <param name="culture"></param>         /// <returns></returns>         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)         {             var flag = bool.Parse(value.ToString());             if(flag)             {                 return Visibility.Visible;             }             else             {                 return Visibility.Collapsed;             }         }          /// <summary>         /// Target到Source         /// </summary>         /// <param name="value"></param>         /// <param name="targetType"></param>         /// <param name="parameter"></param>         /// <param name="culture"></param>         /// <returns></returns>         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)         {             var visibility = Visibility.Collapsed;             if (Enum.TryParse<Visibility>(value.ToString(), out visibility))             {                 if (visibility == Visibility.Collapsed)                 {                     return false;                 }                 else if(visibility == Visibility.Visible)                 {                     return true;                 }                 else                 {                     return false;                 }             }              return false;         }     } }

注意:IValueConverter接口共两个方法,其中Convert方法当Source到Target时调用,ConvertBack方法则是反方向调用。

 

2. 定义资源

 

转换器也是一种资源,要声明资源,首先引入命名空间xmlns:c="clr-namespace:WpfApp4.DataConverter",如下所示:

<Window.Resources> 	<c:BoolToVisilityConverter x:Key="boolToVisility"></c:BoolToVisilityConverter> </Window.Resources>

 

3. 调用类型转换

 

在Binding时,调用资源Visibility="{Binding ElementName=chk01, Path=IsChecked, Converter={StaticResource boolToVisility}}"。通过复选框的选择与否,控制控件的显示与隐藏,如下所示:

<StackPanel Orientation="Horizontal" Grid.Row="0"> 	<CheckBox Content="显示" x:Name="chk01"></CheckBox> </StackPanel> <StackPanel Orientation="Horizontal" Grid.Row="1" Visibility="{Binding ElementName=chk01, Path=IsChecked, Converter={StaticResource boolToVisility}}"> 	<TextBlock Text="年龄" VerticalAlignment="Center"></TextBlock> 	<TextBox x:Name="tbAge" Width="120" Height="25" Margin="10" Validation.Error="tbAge_Error" VerticalContentAlignment="Center"> 		<TextBox.Text> 			<Binding Path="Age" UpdateSourceTrigger="PropertyChanged" NotifyOnValidationError="True"> 				<Binding.ValidationRules> 					<v:RangeValidationRule ValidatesOnTargetUpdated="True"></v:RangeValidationRule> 				</Binding.ValidationRules> 			</Binding> 		</TextBox.Text> 	</TextBox> 	<TextBlock VerticalAlignment="Center" Text="{Binding DataError}" Foreground="Red"></TextBlock> </StackPanel>

 

4. 数据类型转换示例演示

 

浅谈WPF之Binding时数据校验和类型转换

 

源码下载

 

本实例源码相对简单,如果需要源码下载,可关注公众号,回复关键字DATAVC进行获取,如下所示:

浅谈WPF之Binding时数据校验和类型转换

以上就是【浅谈WPF之Binding时数据校验和类型转换】的全部内容,关于更多详细内容,可参考官方文档。希望能够一起学习,共同进步。