首页 > 其他分享 >浅谈WPF之Binding时数据校验和类型转换

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

时间:2024-03-04 21:11:06浏览次数:22  
标签:类型转换 return 浅谈 object Binding 校验 public

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

在数据绑定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. 数据校验示例演示

 

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

 

数据类型转换

 

在数据绑定时,如果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. 数据类型转换示例演示

 

 

源码下载

 

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

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

标签:类型转换,return,浅谈,object,Binding,校验,public
From: https://www.cnblogs.com/hsiang/p/18050883

相关文章

  • 浅谈C语言结构体中多文件的使用
    最近在学单片机C51,手中一个实验需要使用到结构体。但是多文件结构体搞了很久都没成功,在网上找资料文档也是眼花缭乱,对我这个菜鸡中的菜鸡很不友好。搞了1天总算完成了,把自己的亲身经历奉献给大家,供各位参考。有不对的地方也希望高手指出。首先新建3个文件main.c/a.h/a.ca.h写入......
  • 降本增效绝非抠门盘剥,浅谈成本的3大创新认知【精益洞见】
    面临复杂市场环境带来的挑战,GE认识到需要改变决策模式与交付能力。通过Fastworks计划,GE实行了以客户为中心的精益创新方法。通过形成跨部门团队,重视基于客户反馈迭代来验证创新思路。GE在多个领域推广应用Fastworks,取得良好效果。工业巨人GE采用类似初创企业的模式来培养内部......
  • 浅谈差分
    1.前言前置芝士:基本树上操作,lca。(用于树上差分。)如有错误,欢迎各位大佬指出。(顺便复习一下远古算法。)2.什么是差分我们先给定一个数组\(a\),长度为\(n\),我们可以构造一个差分数组\(b\),使得对于任意的\(i(1\lei\len)\),\(\displaystyle\sum_{j=1}^{i}b_j=a_i\)。那......
  • 浅谈微服务
    1.为服务落地根基:高可用性服务可用性+伸缩性:集群+负载均衡2.单体架构——>单个分布式架构从自己连数据库获取数据——————>调用WebAPI获取数据点击查看代码stringurl="http://localhost:8080/api/users/all";//808180828083stringconten......
  • 写少一点/ARCHITECTURE/JavaScript类型转换/Logitech Options一直转圈
    《写少一点》https://www.yuque.com/beilo/simpread/1709260496568《ARCHITECTURE文件》https://www.yuque.com/beilo/simpread/1709260486335例子https://github.com/rust-lang/rust-analyzer/blob/d7c99931d05e3723d878bea5dc26766791fa4e69/docs/dev/architecture.md《Java......
  • WPF Binding 绑定标记扩展
    参考绑定标记扩展Binding类环境软件/系统版本说明WindowsWindows10专业版22H219045.4046MicrosoftVisualStudioMicrosoftVisualStudioCommunity2022(64位)-17.6.5Microsoft.NetSDK8.0.101手动安装Microsoft.NetSDK7.0.306Mi......
  • 浅谈计算几何
    从目前局势来看,@0616allen要被处刑了呢前置知识:维度:维度是一个非常抽象的东西。在生活中常用的是\(0\)到\(3\)维,其对应如下:\(0\)维:点\(1\)维:线\(2\)维:面\(3\)维:体每一维经过移动可以变成更高维,如点移动变成线,面移动变成体。这不就不怕二向箔了吗向量:向量,顾名......
  • 浅谈EK求网络流 & 最小费用最大流
    1.简介:网络流,指的是一种图上问题。首先我们要知道什么是网络。网络的性质如下:有且仅有一个点入度为0,且只有一个点出度为0,我们把入读为0的点叫做源点,出度为0的点为汇点。网络是一个有向图,且有边权。那么流是什么呢?考虑对于下面这个网络:其中\(s\)是源点,\(t\)......
  • SpringMVC系列之(六)自定义类型转换器
    自定义类型转换器SpringMVC在进行请求参数绑定时,自动进行了类型转换,前端传来的参数都是字符串,而控制器中的方法在接收时,可能会用到其他数据类型(如:Date、Integer、Double等),以日期类型为例,前端传的日期格式多样,SpringMVC自动转换类型的格式(2011/11/11)支持不了这么多类型,故有的日期......
  • C++11的类型转换
    //C类型转换/*C语言:显式和隐式类型转换1.隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译失败2.显式类型转化:需要用户自己处理.隐式类型:界定:相关类型,相近类型,意义相似的类型可以发生类型转换,如整型和浮点可以发生类型转换,因为他们都表示数据的大......