在WPF中一种较好的绑定Enums数据方法
引言
在你使用wpf应用程序开发的时候,是否需要进行数据绑定到Enum数据呢?在这篇文章中,我将向你展示在WPF中处理Enum数据绑定的方法。
假设存在一个这样的Enum数据的定义,具体内容如下文代码中所示:
namespace LocalizeFrameworkWpfApp
{
public enum Status
{
Horrible,
Bad,
SoSo,
Good,
Better,
Best
}
}
一、WPF中的通常处理方法
1.1 添加引用
在MainWindow.xaml文件中从mscorlib中引入命名空间System。
xmlns:sys="clr-namespace:System;assembly=mscorlib"
1.2 创建一个ObjectDataProvider资源
在此步骤中,你需要创建一个ObjectDataProvider的资源,并给它一个键名x:Key="DataFromEnum",这样就可以使用DataFromEnum在代码中使用它。并且你需要给MethodName设置为Enum类型上存在的GetValues,然后将ObjectType设置为Enum类型。接下来,你将需设置ObjectDataProvider.MethodParameters的Enum类型。最后,你添加的ObjectDataProvider资源如下面代码所示
<Window.Resources>
<ObjectDataProvider
x:Key="DataFromEnum"
MethodName="GetValues"
ObjectType="{x:Type sys:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:Status">
</x:Type>
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
1.3 Binding数据处理
现在,你可以使用数据绑定了。例如,想将数据绑定到ComboBox上面,那么你需要设置ItemSource为一个新的绑定,并将数据源绑定到我们上面定义的名为DataFromEnum的资源。
<Grid>
<ComboBox
MinWidth="150"
HorizontalAlignment="Center"
VerticalAlignment="Center"
ItemsSource="{Binding Source={StaticResource DataFromEnum}}">
</ComboBox>
</Grid>
到现在为止,所有的已经处理完成,运行程序可以看到数据已经正确绑定到ComboBox上面。

二、较好的处理方法
让我们来看看当数据绑定Enum类型时,如何使用WPF特性来改进代码的使用和可读性。首先,想封装Enum类型的绑定而不需要ObjectDataProvider资源的逻辑处理,还希望不需要必须定义资源才能在xaml中使用绑定功能。理想情况下,应该像处理普通对象的绑定一样,将所有内容都内联处理。为此,需要利用定制MarkupExtension的帮助类。这个扩展将简单的接受Enum类型,然后为控件创建一个可绑定Enum值的列表,这种实现其实很简单。
2.1 MarkupExtension帮助类
MarkupExtension帮助类定义如下:
namespace LocalizeFrameworkWpfApp
{
public class EnumBindingSourceExtension:MarkupExtension
{
private Type _enumType;
public Type EnumType
{
get { return _enumType; }
set
{
if (value != _enumType)
{
if (null != value)
{
var enumType = Nullable.GetUnderlyingType(value) ?? value;
if (!enumType.IsEnum)
{
throw new ArgumentException("Type must bu for an Enum");
}
}
_enumType = value;
}
}
}
public EnumBindingSourceExtension()
{
}
public EnumBindingSourceExtension(Type enumType)
{
EnumType = enumType;
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (null == _enumType)
{
throw new InvalidOperationException("The EnumTYpe must be specified.");
}
var actualEnumType = Nullable.GetUnderlyingType(_enumType) ?? _enumType;
var enumValues = Enum.GetValues(actualEnumType);
if (actualEnumType == _enumType)
{
return enumValues;
}
var tempArray = Array.CreateInstance(actualEnumType, enumValues.Length + 1);
enumValues.CopyTo(tempArray, 1);
return tempArray;
}
}
}
2.2 Binding数据处理
<Grid>
<StackPanel>
<ComboBox
MinWidth="150"
HorizontalAlignment="Center"
ItemsSource="{Binding Source={StaticResource DataFromEnum}}">
</ComboBox>
<ComboBox
MinWidth="150"
HorizontalAlignment="Center"
ItemsSource="{Binding Source={local:EnumBindingSource {x:Type local:Status}}}">
</ComboBox>
</StackPanel>
</Grid>
看一下运行结果:

三、扩展:添加Enum类型的描述(Description)支持
现在我们可以不用使用ObjectDataProvider资源进行Enum类型的绑定工作了。这两种方法进行对比一下,详细这个新方法会让你耳目一新,像发现了新大陆一般。
而Enum类型的值一般使用在程序中,而为了让用户获得更好的使用体验,一般都会在枚举值前面添加上属性:Description描述。为了完成此工作,我们只需使用TypeConverter进行转换。
namespace LocalizeFrameworkWpfApp
{
public class EnumDescriptionTypeConverter:EnumConverter
{
public EnumDescriptionTypeConverter(Type type) : base(type)
{
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
if (null != value)
{
FieldInfo fi = value.GetType().GetField(value.ToString());
if (null != fi)
{
var attributes =
(DescriptionAttribute[]) fi.GetCustomAttributes(typeof(DescriptionAttribute), false);
return ((attributes.Length > 0) && (!string.IsNullOrEmpty(attributes[0].Description)))
? attributes[0].Description
: value.ToString();
}
}
return string.Empty;
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
然后对定义的枚举值添加上[Description]属性
namespace LocalizeFrameworkWpfApp
{
[TypeConverter(typeof(EnumDescriptionTypeConverter))]
public enum Status
{
[Description("This is horrible")]
Horrible,
[Description("This is Bad")]
Bad,
[Description("This is SoSo")]
SoSo,
[Description("This is Good")]
Good,
[Description("This is Better")]
Better,
[Description("This is Best")]
Best
}
}
程序运行结果:

可以看到,我们添加了[Description]属性时,这两种方法都可以将[Description]属性的值绑定到指定控件中。
如果你觉得不错,扫描下面公众号给个关注,在此感谢!!

在WPF中一种较好的绑定Enums数据方法的更多相关文章
- WPF中的ListBox实现按块显示元素的方法
本文实例讲述了WPF中的ListBox实现按块显示元素的方法.分享给大家供大家参考,具体如下: 注意:需要设置ListBox的属性 ScrollViewer.HorizontalScrollBarVi ...
- WPF中ItemsControl应用虚拟化时找到子元素的方法
原文:WPF中ItemsControl应用虚拟化时找到子元素的方法 wpf的虚拟化技术会使UI的控件只初始化看的到的子元素, 而不是所有子元素都被初始化,这样会提高UI性能. 但是我们经常会遇到一个 ...
- 整理:WPF中应用附加事件制作可以绑定命令的其他事件
原文:整理:WPF中应用附加事件制作可以绑定命令的其他事件 目的:应用附加事件的方式定义可以绑定的事件,如MouseLeftButton.MouseDouble等等 一.定义属于Control的附加事 ...
- 转:WPF中ListBox的创建和多种绑定用法
先从最容易的开始演示ListBox控件的创建. Adding ListBox Items下面的代码是向ListBox控件中添加多项ListBoxItem集合.XAML代码如下:<ListBox ...
- WPF中使用相对资源来进行绑定,数据源是通过DataContext来指定的
1. 最外层是Window是对象,Window的ItemsControl使用了ItemsTemplate,然后在ItemsTemplate中要绑定Language属性, 而整个Window的数据源是通 ...
- WPF中三种方法得到当前屏幕的宽和高
WPF程序中的单位是与设备无关的单位,每个单位是1/96英寸,如果电脑的DPI设置为96(每个英寸96个像素),那么此时每个WPF单位对应一个像素,不过如果电脑的DPI设备为120(每个英寸120个像 ...
- .Net中几种常见的页面跳转传值方法
1.ASP Server对象Execute方法 ASP Server对象的Execute方法可以在执行当前页面的过程中将另一个页面执行结果的内容插入到当前页面的输出中.Execute方法带一个参数,是 ...
- android在代码中四种设置控件背景颜色的方法(包含RGB)
转载请注明出处: http://blog.csdn.net/fth826595345/article/details/9208771 TextView tText=(TextView) findVi ...
- Javascript中两种最通用的定义类的方法
在Javascript中,一切都是对象,包括函数.在Javascript中并没有真正的类,不能像C#,PHP等语言中用 class xxx来定义.但Javascript中提供了一种折中的方案:把对象定 ...
随机推荐
- VUE开发(二)nginx配合vue来实现前后端分离部署
一.引言 由于本地是采用vue+spring boot实现的前后端分离项目,本机启动的时候先启动后场服务,再单独启动vue工程,然后可以实现全流程贯穿,但是我们要部署到服务器上的时候,一般都是打一个j ...
- [SUCTF 2019]EasySQL1 及sql_mode
(我被虐到了,呜呜呜) 当 sql_mode 设置了 PIPES_AS_CONCAT 时,|| 就是字符串连接符,相当于CONCAT() 函数 当 sql_mode 没有设置 PIPES_AS_CON ...
- Tomcat学习小记(一)
1.Tomcat概述 Tomcat 服务器是一个开源的轻量级Web应用服务器,擅长处理动态资源,在中小型系统和并发量小的场合下被普遍使用,是开发和调试Servlet.JSP 程序的首选. Tomcat ...
- Spring学习(九)--Spring的AOP
1.配置ProxyFactoryBean Spring IOC容器中创建Spring AOP的方法. (1)配置ProxyFactoryBean的Advisor通知器 通知器实现定义了对目标对象进行增 ...
- 如何在服务器端使用ASP.NET Core 2 教程
dhtmlxGantt用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表.可满足项目管理应用程序的所有需求,是最完善的甘特图图表库.它允许你创建动态甘特图,并以一个方便的图形化方式可视化项目进度. ...
- springboot项目打包瘦身
默认情况下,Spring Boot 项目发布时会将项目代码和项目的所有依赖文件一起打成一个可执行的 jar 包.但如果项目的依赖包很多,那么这个文件就会非常大.这样每次即使只改动一点东西,就需要将整个 ...
- Java学习day03
day03 课堂笔记 1.数据类型 2.总结第二章到目前为止所学内容: * 标识符 * 关键字 * 字面值 * 变量 成员变量如果没有赋值,系统会自动赋值,而局部变量不手动赋值,则会编译不通过. * ...
- CUMTCTF'2020 未完成 wp
Web babysqli burp抓包,发现有 的过滤,用/**/过滤空格. 报错注入 payload username=admin&password='/**/or/**/extractva ...
- java 线程池、多线程实战(生产者消费者模型,1 vs 10) 附案例源码
导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...
- 文档生成工具——Doxygen
参考: 1.https://blog.csdn.net/liao20081228/article/details/77322584 2.https://blog.csdn.net/wang150619 ...