65.9K
CodeProject 正在变化。 阅读更多。
Home

通用 ValueConverter,用于将枚举绑定到复选框

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.75/5 (12投票s)

2011年10月15日

CPOL

3分钟阅读

viewsIcon

32858

downloadIcon

370

通用 ValueConverter,用于将枚举绑定到复选框

摘要

很多时候,一个表单上有一组单选按钮与单个枚举关联。 很多开发人员会为每个单选按钮在ViewModel中创建一个单独的属性。 我不喜欢这样做。 首先,我认为这在ViewViewModel之间存在太多的依赖关系。 它还会向ViewModel添加一大堆属性,这只会使ViewModel更大,并且需要额外的代码才能将其转换为枚举。 真正需要的是每个枚举的单个属性和一个通用的ValueConverter

背景

在多次不得不处理单选按钮和ViewModel之后,我终于决定创建一种处理它们的通用方法。

实现

要将枚举绑定到一组单选按钮的IsChecked属性,需要一个ValueConverter;如果没有转换器,就无法将枚举绑定到bool。 可以为每个单选按钮创建一个单独的ValueConverter类,但这不是必需的,因为ValueConverter方法具有一个参数,该参数通过使用Binding的ConverterParameter参数在XAML中设置。 想法是每个单选按钮的IsChecked参数都使用EnumValueConverter绑定到Enumeration属性,其ConverterParameter等于一个string,该string是特定枚举的名称。

class EnumValueConverter : IValueConverter
{
	public object Convert(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
	{
		if (value == null || parameter == null)
			return false;
		return value.ToString() == parameter.ToString();
	}

	public object ConvertBack(object value, Type targetType, 
		object parameter, System.Globalization.CultureInfo culture)
	{
		if (value == null || parameter == null)
			return null;
		var rtnValue = parameter.ToString();
		try
		{
			object returnEnum = Enum.Parse(targetType, rtnValue);
			return returnEnum;
		}
		catch
		{
			return null;
		}
	} 
}

在示例代码中,我添加了三个调试方法来帮助查找错误,但为了清楚起见,已删除了这些方法。 可以看出,代码非常简单明了。 在Convert方法中,使用ToString()方法将ViewModel中的枚举转换为string,然后将其与ConverterParmeter进行比较;如果相等,则返回的值为true。 在ConvertBack方法中,如果值参数存在,则使用Enum.Parse方法将控制中的ConverterParmeter转换为ViewModel的相应枚举。 幸运的是,这可行,因为对于单选按钮,它们只需要处理更改为选中状态,因此无需处理更改为未选中状态;那是自动的。 如果Parse不起作用,则返回null(对于null值和参数参数也是如此,它没有效果,因为null对于枚举无效(Binding不允许更改无效值))。

将XAML连接到属性和转换器非常简单。 在示例中,有一个非常简单的enum

public enum TestEnum
{
	A, B, C
}

此枚举的ViewModel中的属性也非常简单

public TestEnum EnumBinding
{
	get
	{
		return _enumBinding;
	}
	set
	{
		if (_enumBinding != value)
		{
			_enumBinding = value;
			if (PropertyChanged != null)
				PropertyChanged(this, new 
				PropertyChangedEventArgs("EnumBinding"));
		}
	}
}

现在只需要XAML,其中包括转换器的资源定义和带有绑定定义的复选框,这些绑定定义使用转换器和ConverterParameter

<Window x:Class="GenericEnumValueConverter.MainWindow"
		xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
		xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
		xmlns:local="clr-namespace:GenericEnumValueConverter"
		Title="Enumerator Value Converter Example" 
		Height="200" Width="250">
	<Window.Resources>
		<local:EnumValueConverter x:Key="EnumValueConverter"/>
	</Window.Resources>
	<StackPanel HorizontalAlignment="Center" 
		    VerticalAlignment="Center">
		<RadioButton Content="A" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=A}"/>
		<RadioButton Content="B" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=B}"/>
		<RadioButton Content="C" 
			IsChecked="{Binding EnumBinding,
				Converter={StaticResource EnumValueConverter},
				ConverterParameter=C}"/>
	</StackPanel>
</Window>

实际示例包括一个TextBox,用于确认枚举的属性实际上是单选按钮的值,以及一个包含错误值的额外单选按钮,用于显示XAML中存在错误枚举值时发生的情况(在调试期间,按下“Bad Value”单选按钮会在“输出”窗口中创建一个消息)。

结论

这是一种非常简洁的将枚举连接到单选按钮的方法。 相同的转换器也可以用于其他目的,只需添加一些额外的代码,例如根据枚举指定的状态设置控件的可见性(需要将bool值转换为Visibility枚举)。 它减少了ViewModel的很多复杂性,并为所有枚举绑定到CheckBox(或其他Control)的实例使用单个转换器。 总之,这是一种非常简洁的减少代码和提高可维护性的方法。

历史

  • 2011 年 10 月 15 日:初始版本
© . All rights reserved.