糟糕,我说得太早了!至少在Silverlight 3中有一个完美的解决方案。(可能只在3中,因为这个线程表明与此相关的错误已在Silverlight 3中修复。)
基本上,您需要一个单一的转换器来处理ItemsSource
属性,但它可以是完全通用的,而不使用任何被禁止的方法,只要您将其传递给一个类型为MyEnum
的属性的名称即可。并且绑定到SelectedItem
非常简单;无需转换器!嗯,至少只要您不想通过例如DescriptionAttribute
为每个枚举值提供自定义字符串,那么...对于那个,可能需要另一个转换器;希望我能使它通用。
更新:我制作了一个转换器,并且它可以工作!不幸的是,现在我必须绑定到SelectedIndex
,但没关系。使用这些人:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Windows.Data;
namespace DomenicDenicola.Wpf
{
public class EnumToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (int)value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return Enum.Parse(targetType, value.ToString(), true);
}
}
public class EnumToIEnumerableConverter : IValueConverter
{
private Dictionary<Type, List<object>> cache = new Dictionary<Type, List<object>>();
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var type = value.GetType();
if (!this.cache.ContainsKey(type))
{
var fields = type.GetFields().Where(field => field.IsLiteral);
var values = new List<object>();
foreach (var field in fields)
{
DescriptionAttribute[] a = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (a != null && a.Length > 0)
{
values.Add(a[0].Description);
}
else
{
values.Add(field.GetValue(value));
}
}
this.cache[type] = values;
}
return this.cache[type];
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
使用以下类型的XAML绑定:
<ComboBox x:Name="MonsterGroupRole"
ItemsSource="{Binding MonsterGroupRole,
Mode=OneTime,
Converter={StaticResource EnumToIEnumerableConverter}}"
SelectedIndex="{Binding MonsterGroupRole,
Mode=TwoWay,
Converter={StaticResource EnumToIntConverter}}" />
And this sort of resource-declaration XAML:
<Application xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ddwpf="clr-namespace:DomenicDenicola.Wpf">
<Application.Resources>
<ddwpf:EnumToIEnumerableConverter x:Key="EnumToIEnumerableConverter" />
<ddwpf:EnumToIntConverter x:Key="EnumToIntConverter" />
</Application.Resources>
</Application>
非常感谢您的评论,因为我对XAML/Silverlight/WPF等方面还很新手。例如,EnumToIntConverter.ConvertBack
会很慢吗?我是否应该考虑使用缓存?
EnumToIntConverter.ConvertBack()
中,你可以使用return Enum.ToObject (targetType, value);
来返回值,而不是通过缓慢的字符串转换和解析。 - Duckboy