WPF转换器之通用转换器
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
参数规则【各组比较值:比较条件(&或|):true返回值:false返回值:返回值类型枚举】
多值转换器的参数规则略显麻烦,但是也和三元表达式类似,只不过多了比较条件和返回值枚举类型,这里有人要问了为什么单值转换器不需要声明返回值枚举而多值转换器需要,这是因为多值转换器的返回值不返回实际类型的话,返回类型会失效,WPF的默认转换器似乎没有起到作用。这个问题我也正在研究,所以先定义一个返回值枚举用来转换返回值的类型。姑且算一个临时解决方案吧
public class MultiObjectConverter : IMultiValueConverter
{
/// <summary>
/// 多值转换器
/// </summary>
/// <param name="values">参数值数组</param>
/// <param name="parameter">
/// <para>参数</para>
/// <para>各组比较值:比较条件(&或|):true返回值:false返回值:返回值类型枚举</para>
/// <para>v1;v2-1|v2-2;v3:&: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转换器之通用转换器的更多相关文章
- WPF转换器之值转换器
WPF有两转转换器,一种是值转换器,另一种多值转换器,在开发过程中经常会从数据拉一些数据过来,比如存储性别的时候往往会用0或1,但在界面上肯定是要显示男或女,那么这个时候就可以用上值转换器 编写转换器 ...
- pdf转换成word转换器免费版
在平时的办公中,我们只需要有一款比较好用的pdf转换成word转换器,就能提高我们的工作效率,但是国内外的pdf转换成word转换器应该怎么选呢?小编因为是文职工作者,所以在日常的实践中选出了ABBY ...
- [No000012C]WPF(4/7)类型转换器和标记扩展[译]
介绍 之前讨论了WPF的基础架构,然后逐步开始学习布局面板,转换,介绍了不同的控件,容器,UI转换等.在这篇文章中,我将讨论每个创建XAML应用前的开发人员应该了解的关于XAML最重要的东西. 标记扩 ...
- ES6转换器之Babel
ES6部分功能没有支持,所以想学习ES6,得先有个转换器,就是将ES6的代码转换为ES5. 我这里用的是Gulp + Bable的形式来将ES6转换为ES5的. 前提: (1).Gulp和Bable都 ...
- WPF报表自定义通用可筛选列头-WPF特工队内部资料
由于项目需要制作一个可通用的报表多行标题,且可实现各种类型的内容显示,包括文本.输入框.下拉框.多选框等(自定的显示内容可自行扩展),并支持参数绑定转换,效果如下: 源码结构 ColumnItem类: ...
- mybatis枚举自动转换(通用转换处理器实现)
https://blog.csdn.net/fighterandknight/article/details/51520595 https://blog.csdn.net/fighterandknig ...
- WPF Binding的值转换器
注意:值转换器中用于传入额外信息的参数 parameter 在 Binding 时使用 Binding 对象的 ConverterParameter 属性指定,但是设置了 ConverterParam ...
- springboot整合mongodb问题1-Decimal128和BigDecimal的转换之mongodb转换器使用(转)
转自:https://blog.csdn.net/weixin_41792559/article/details/79575524 1.Decimal128的了解由于mongodb4.3以上新加了De ...
- 在spring data jpa中使用自定义转换器之使用枚举转换
转载请注明http://www.cnblogs.com/majianming/p/8553217.html 在项目中,经常会出现这样的情况,一个实体的字段名是枚举类型的 我们在把它存放到数据库中是需要 ...
随机推荐
- 写JS自执行函数时要注意的
JS是非强类型语言,且IDE也不够智能,所以经常会在语句结束时漏写了分号,一般情况下这是不影响运行的, 但如果后面跟上的是一段自执行的函数,就会报出 "..... is not functi ...
- ionic3 环境配置 + 運行第一個項目
1.首先我們先下載個 nodejs安裝包 地址:https://nodejs.org/en/ 安裝 檢查是否安裝成功,打開命令提示符 輸入 node -v 回車 查看版本 結果: 2.安裝ionic ...
- python入门小记
一.help python中的帮助手册,对于初学者,多多使用help,多看看原生注释-- 1.help的使用 1.命令需要使用双引号或者单引号括起来,不使用引号引起来会报错 2.类或者函数(方法)不需 ...
- gawk的用法
GNU gawk工具的功能是将指定文件中符合指定模式(pattern)的行按指定的动作(action)进行格式化处理 语法:gawk [options] [program] [file-lis ...
- js___原生js轮播
原生js轮播 作为一名前端工程师,手写轮播图应该是最基本掌握的技能,以下是我自己原生js写的轮播,欢迎指点批评: 首先css代码 a{text-decoration:none;color:#3DBBF ...
- thinkphp3.2.3 版本使用redis缓存添加认证
我在使用thinkphp3.2.3的时候 发现如果是使用redis缓存 设置了认证的redis能连接成功 却无法 set 操作 ,检查发现是没有认证导致的 $redis->auth这一步没有, ...
- Ecshop去掉模版中随机出现Ecshop版权的方法
EC如果是免费用户用的话,模版里面会随机出现 powered by ecshop 的字样,看了一下原来是在COMMON.JS里面写的一段代码,删除掉就可以解决掉了,方法如下: 打开 js/commo ...
- 安装旧版的docker-engine-1.12.6
执行kubeadm init --api-advertise-addresses=172.16.160.211命令的时候,提示docker版本太新了 想要安装旧版docker,可以使用以下方法: yu ...
- 如何给两个swiper建立关系
单个swiper已经满足不了需求了. 各种花式轮播已经慢慢进入市场.swiper该如何立足,那么请看. <div class="swiper-container"> & ...
- Docker 初步认识
1.docker 是什么? 一个开源的应用容器引擎,个人理解 就是虚拟的应用运行环境. 2.安装Docker for windows 下载地址 :https://store.docker.com/ed ...