在开发过程中,经常需要将一种类型的值转换为另一种类型的值,例如将枚举值转换为相应的图像。传统的方法是编写一个包含自定义代码(例如switch-case语句)的值转换器。但是,这种方法在处理大量转换时可能会变得繁琐且难以维护。为了解决这个问题,将介绍一种新的转换器——DictionaryValueConverter,它允许定义一组键值对,并自动为完成映射工作。
以下代码展示了如何使用DictionaryValueConverter。在这个例子中,将三个枚举值映射到三个不同的位图图像。每个Values属性中的值都是通过其x:Key映射的图像。
<converters:DictionaryValueConverter x:Key="propertyTypeToImage">
<converters:DictionaryValueConverter.Values>
<BitmapImage x:Key="{x:Static local:PropertyType.Name}" UriSource="Name.png" />
<BitmapImage x:Key="{x:Static local:PropertyType.Age}" UriSource="Age.png" />
<BitmapImage x:Key="{x:Static local:PropertyType.Phone}" UriSource="Phone.png" />
</converters:DictionaryValueConverter.Values>
</converters:DictionaryValueConverter>
这种方法非常酷,可能会问,是否可以用它来将布尔值转换为可见性?理论上是可行的,因为代码中没有阻止这样做。实际上,需要一种方法来指定“true”和“false”布尔值作为键。不幸的是,XAML2006不允许x:Key具有复杂值(使用属性元素语法)。这个问题在XAML 2009中得到了解决,但WPF目前还不支持。为了解决这个问题,可以定义“true”和“false”值的常量,并使用x:Static标记扩展来提供键。
public static class BooleanValues
{
public const bool True = true;
public const bool False = false;
}
<converters:DictionaryValueConverter x:Key="booleanToVisibilityConverter">
<converters:DictionaryValueConverter.Values>
<Visibility x:Key="{x:Static local:BooleanValues.True}">
Visible
</Visibility>
<Visibility x:Key="{x:Static local:BooleanValues.False}">
Collapsed
</Visibility>
</converters:DictionaryValueConverter.Values>
</converters:DictionaryValueConverter>
DictionaryValueConverter的实现如下:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows;
using System.Windows.Data;
namespace Common.Converters
{
public class DictionaryValueConverter : IValueConverter
{
public Type KeyType { get; set; }
public Dictionary<object, object> Values { get; set; }
public DictionaryValueConverter()
{
Values = new Dictionary<object, object>();
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (KeyType == null)
{
KeyType = Values.Keys.First().GetType();
}
if (KeyType.IsEnum)
{
value = Enum.ToObject(KeyType, value);
}
if (Values.ContainsKey(value))
{
return Values[value];
}
return DependencyProperty.UnsetValue;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return DependencyProperty.UnsetValue;
}
}
}