WPF中的转换器是一个非常好的数据类型转换解决方案,实用和强大, 它的作用是将源数据转换为WPF自身需要的类型,对数据实体没有侵略性,会在项目工程中频繁使用。所以掌握转换器是WPF开发的必备技能。

我刚接触转换器的时候,没有考虑通用性,每次遇到一个转换需求都会去创建一个新的转换器,久而久之,项目中的转换器已多如牛毛

这当然是我无法容忍的,我决定用一种通用转换器来代替绝大部分性质相同的转换操作,通过约定一套参数规则来适应不同的转换场景,达到转换器复用的目的。

转换器分为两种,IValueConverter(单值转换器)和IMultiValueConverter(多值转换器)

单值通用转换器 ObjectConverter

参数规则【比较值1|比较值2:true返回值:false返回值】

仔细一看,这个参数规则其实和三元表达式的含义相同,当源数据等于比较值1或者比较值2的时候,返回true返回值,否则返回false返回值

有了这个规则,就可以实现通用转换需求了,ObjectConverter源码如下

 public class ObjectConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
string[] parray = parameter.ToString().ToLower().Split(':'); //将参数字符分段 parray[0]为比较值,parray[1]为true返回值,parray[2]为false返回值
if (value == null)
return parray[2]; //如果数据源为空,默认返回false返回值
if (parray[0].Contains("|")) //判断有多个比较值的情况
return parray[0].Split('|').Contains(value.ToString().ToLower()) ? parray[1] : parray[2]; //多值比较
return parray[0].Equals(value.ToString().ToLower()) ? parray[1] : parray[2]; //单值比较
} public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
var returnValue = "otherValue";
string[] parray = parameter.ToString().ToLower().Split(':');
if (value == null)
return returnValue;
var valueStr = value.ToString().ToLower();
if (valueStr != parray[1])
return returnValue;
else
return parray[0].Contains('|') ? parray[0].Split('|')[0] : parray[0];
}
}

 ObjectConverter的使用

 <converter:ObjectConverter x:Key="objConverter"/>

 <Border Visibility="{Binding PanelStatus,  Converter={StaticResource objConverter},ConverterParameter=true:Visible:Collapsed}">

 <Border Background="{Binding BgColor,  Converter={StaticResource objConverter},ConverterParameter=1:Red:Blue}">

 <TextBlock Text="{Binding Type, Converter={StaticResource objConverter},ConverterParameter=1|2:VIP会员:普通会员}"/>

多值通用转换器 MultiObjectConverter

参数规则【各组比较值:比较条件(&amp;或|):true返回值:false返回值:返回值类型枚举】

多值转换器的参数规则略显麻烦,但是也和三元表达式类似,只不过多了比较条件和返回值枚举类型,这里有人要问了为什么单值转换器不需要声明返回值枚举而多值转换器需要,这是因为多值转换器的返回值不返回实际类型的话,返回类型会失效,WPF的默认转换器似乎没有起到作用。这个问题我也正在研究,所以先定义一个返回值枚举用来转换返回值的类型。姑且算一个临时解决方案吧

 public class MultiObjectConverter : IMultiValueConverter
{
/// <summary>
/// 多值转换器
/// </summary>
/// <param name="values">参数值数组</param>
/// <param name="parameter">
/// <para>参数</para>
/// <para>各组比较值:比较条件(&amp;或|):true返回值:false返回值:返回值类型枚举</para>
/// <para>v1;v2-1|v2-2;v3:&amp;:Visible:Collapsed:1</para>
/// </param>
/// <returns></returns>
public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string[] param = parameter.ToString().ToLower().Split(':'); //将参数字符串分段
string[] compareValues = param[].Split(';'); //将比较值段分割为数组
if (values.Length != compareValues.Length) //比较源数据和比较参数个数是否一致
return ConvertValue(param[], param[]);
var trueCount = ; //满足条件的结果数量
var currentValue = string.Empty;
IList<string> currentParamArray = null;
for (var i = ; i < values.Length; i++)
{
currentValue = values[i] != null ? values[i].ToString().ToLower() : string.Empty;
if (compareValues[i].Contains("|"))
{
//当前比较值段包含多个比较值
currentParamArray = compareValues[i].Split('|');
trueCount += currentParamArray.Contains(currentValue) ? : ; //满足条件,结果+1
}
else
{
trueCount += compareValues[i].Equals(currentValue) ? : ; //满足条件,结果+1
}
}
currentParamArray = null;
currentValue = string.Empty;
var compareResult = param[].Equals("&") ?
trueCount == values.Length :
trueCount > ; //判断比较结果
return ConvertValue(compareResult ? param[] : param[], param[]);
} public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
} private object ConvertValue(string result, string enumStr)
{
var convertResult = (ConvertResult)int.Parse(enumStr);
if (convertResult == ConvertResult.显示类型)
return result.Equals("collapsed") ? Visibility.Collapsed : Visibility.Visible;
if (convertResult == ConvertResult.布尔类型)
return System.Convert.ToBoolean(result);
return null; //后续自行扩展
} private enum ConvertResult
{
显示类型 = ,
布尔类型 = ,
字符串类型 = ,
整型 = ,
小数型 = ,
画刷类型 = ,
样式类型 = ,
模板类型 =
}
}

MulitObjectConverter的使用

 <TextBlock Text="test">
<TextBlock.Visibility>
<MultiBinding Converter="{StaticResource mobjConverter}"
ConverterParameter="1|2;true:|:Visible:Collapsed:1">
<Binding Path="Filed1"/>
<Binding Path="Filed2"/>
</MultiBinding>
</TextBlock.Visibility>
</TextBlock>

单值通用转换器和多值通用转换器已经讲完了,读者可以根据自己的需求定制ConverterParameter的规则,实现灵活扩展。欢迎入群交流372754241

WPF转换器之通用转换器的更多相关文章

  1. WPF转换器之值转换器

    WPF有两转转换器,一种是值转换器,另一种多值转换器,在开发过程中经常会从数据拉一些数据过来,比如存储性别的时候往往会用0或1,但在界面上肯定是要显示男或女,那么这个时候就可以用上值转换器 编写转换器 ...

  2. pdf转换成word转换器免费版

    在平时的办公中,我们只需要有一款比较好用的pdf转换成word转换器,就能提高我们的工作效率,但是国内外的pdf转换成word转换器应该怎么选呢?小编因为是文职工作者,所以在日常的实践中选出了ABBY ...

  3. [No000012C]WPF(4/7)类型转换器和标记扩展[译]

    介绍 之前讨论了WPF的基础架构,然后逐步开始学习布局面板,转换,介绍了不同的控件,容器,UI转换等.在这篇文章中,我将讨论每个创建XAML应用前的开发人员应该了解的关于XAML最重要的东西. 标记扩 ...

  4. ES6转换器之Babel

    ES6部分功能没有支持,所以想学习ES6,得先有个转换器,就是将ES6的代码转换为ES5. 我这里用的是Gulp + Bable的形式来将ES6转换为ES5的. 前提: (1).Gulp和Bable都 ...

  5. WPF报表自定义通用可筛选列头-WPF特工队内部资料

    由于项目需要制作一个可通用的报表多行标题,且可实现各种类型的内容显示,包括文本.输入框.下拉框.多选框等(自定的显示内容可自行扩展),并支持参数绑定转换,效果如下: 源码结构 ColumnItem类: ...

  6. mybatis枚举自动转换(通用转换处理器实现)

    https://blog.csdn.net/fighterandknight/article/details/51520595 https://blog.csdn.net/fighterandknig ...

  7. WPF Binding的值转换器

    注意:值转换器中用于传入额外信息的参数 parameter 在 Binding 时使用 Binding 对象的 ConverterParameter 属性指定,但是设置了 ConverterParam ...

  8. springboot整合mongodb问题1-Decimal128和BigDecimal的转换之mongodb转换器使用(转)

    转自:https://blog.csdn.net/weixin_41792559/article/details/79575524 1.Decimal128的了解由于mongodb4.3以上新加了De ...

  9. 在spring data jpa中使用自定义转换器之使用枚举转换

    转载请注明http://www.cnblogs.com/majianming/p/8553217.html 在项目中,经常会出现这样的情况,一个实体的字段名是枚举类型的 我们在把它存放到数据库中是需要 ...

随机推荐

  1. 主题模型(概率潜语义分析PLSA、隐含狄利克雷分布LDA)

    一.pLSA模型 1.朴素贝叶斯的分析 (1)可以胜任许多文本分类问题.(2)无法解决语料中一词多义和多词一义的问题--它更像是词法分析,而非语义分析.(3)如果使用词向量作为文档的特征,一词多义和多 ...

  2. 学习总结------Servlet的简单理解

    1.什么是Servlet Servlet是一个Java编写的程序,在服务器端运行的(如tomcat) Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览 ...

  3. C#的命名管道(named pipe)

    命名管道是一种从一个进程到另一个进程用内核对象来进行信息传输.和一般的管道不同,命名管道可以被不同进程以不同的方式方法调用(可以跨权限.跨语言.跨平台).只要程序知道命名管道的名字,发送到命名管道里的 ...

  4. 收集一些工作中常用的经典SQL语句

    作为一枚程序员来说和数据库打交道是不可避免的,现收集一下工作中常用的SQL语句,希望能给大家带来一些帮助,当然不全面,欢迎补充! 1.执行插入语句,获取自动生成的递增的ID值 INSERT INTO ...

  5. SICIP-1.3-Defining a new function

    定义函数 def <name> (former parament): 函数体(缩进) 环境 全局环境 局部环境 只在函数内部有效 TIP 函数体只在调用的最后执行 抽象化函数 函数域(函数 ...

  6. 如何在linux如何安装nginx服务器

    1.进入命令窗口: 2.进入nginx.org 网站 下载安装包nginx-1.8.0.tar.gz 3.进入下载的文件夹 4.加压下载的压缩包 tar  -zxvf nginx-1.8.0.tar. ...

  7. JavaScript练习笔记整理·3 - 6.25

    欢迎和大家一起来讨论~   基础练习(1):   我的解答为: function array_diff(a, b) { if (b == "") return a; return ...

  8. Kubernetes服务之StatefulSets简介

    StatefulSets在v1.5时还是个beta特性,它取代了v1.4的PetSets特性.PetSets的用户可以参考v1.5的升级指导,将正在运行的PeetSets升级到StatefulSets ...

  9. CYQ.Data V5 分布式自动化缓存设计介绍(二)

    前言: 最近一段时间,开始了<IT连>创业,所以精力和写的文章多数是在分享创业的过程. 而关于本人三大框架CYQ.Data.Aries.Taurus.MVC的相关文章,基本都很少写了. 但 ...

  10. zoom与scale的异同

    zoom与scale的异同点 作为一名前端,尤其是页面要兼容ie浏览器的前端,肯定对着两个属性都很熟悉. zoom和scale都是css中常用的放大和缩小一个元素的方法,在scale还没有成为css3 ...