如何将枚举绑定到WPF中的组合框控件?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (23)

我试图找到一个简单的例子使枚举按原样显示。我见过的所有例子都试图添加显示字符串,但我不想那么复杂。

我有一个类,它拥有我绑定的所有属性,首先将DataContext设置为该类,然后在xaml文件中指定如下所示的绑定:

<ComboBox ItemsSource="{Binding Path=EffectStyle}"/>

但是这并不显示ComboBox作为项目的枚举值。

提问于
用户回答回答于

可以通过在窗口 Loaded事件处理程序中放置以下代码从代码执行此操作,例如:

yourComboBox.ItemsSource = Enum.GetValues(typeof(EffectStyle)).Cast<EffectStyle>();

如果需要在XAML中绑定它,需要使用ObjectDataProvider创建对象作为绑定源:

<Window x:Class="YourNamespace.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:StyleAlias="clr-namespace:Motion.VideoEffects">
    <Window.Resources>
        <ObjectDataProvider x:Key="dataFromEnum" MethodName="GetValues"
                            ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="StyleAlias:EffectStyle"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <ComboBox ItemsSource="{Binding Source={StaticResource dataFromEnum}}"
                  SelectedItem="{Binding Path=CurrentEffectStyle}" />
    </Grid>
</Window>

注意代码:

xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:StyleAlias="clr-namespace:Motion.VideoEffects"

用户回答回答于

我尽量避免在xaml中使用

<ObjectDataProvider>

当我想将一个Enum文本绑定到ComboBox时,这样:

public enum PlayerClass
{
  // add an optional blank value for default/no selection
  [Description("")]
  NOT_SET = 0,
  [Description("Shadow Knight")]
  SHADOW_KNIGHT,
  ...
}

我用几个方法创建了辅助类来处理枚举。一种方法获取特定值的描述,另一种方法获取某个类型的所有值及其描述。

public static class EnumHelper
{
  public static string Description(this Enum eValue)
  {
    var nAttributes = eValue.GetType().GetField(eValue.ToString()).GetCustomAttributes(typeof(DescriptionAttribute), false);
    if (nAttributes.Any())
      return (nAttributes.First() as DescriptionAttribute).Description;

    // If no description is found, the least we can do is replace underscores with spaces
    // You can add your own custom default formatting logic here
    TextInfo oTI = CultureInfo.CurrentCulture.TextInfo;
    return oTI.ToTitleCase(oTI.ToLower(eValue.ToString().Replace("_", " ")));
  }

  public static IEnumerable<ValueDescription> GetAllValuesAndDescriptions(Type t)
  {
    if (!t.IsEnum)
      throw new ArgumentException("t must be an enum type");

    return Enum.GetValues(t).Cast<Enum>().Select((e) => new ValueDescription() { Value = e, Description = e.Description() }).ToList();
  }
}

接下来,创建一个ValueConverter。继承MarkupExtension使得在XAML中使用起来更容易

[ValueConversion(typeof(Enum), typeof(IEnumerable<ValueDescription>))]
public class EnumToCollectionConverter : MarkupExtension, IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return EnumHelper.GetAllValuesAndDescriptions(value.GetType());
  }
  public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
  {
    return null;
  }
  public override object ProvideValue(IServiceProvider serviceProvider)
  {
    return this;
  }
}
private PlayerClass p_eClass;

public PlayerClass SelectedClass
{
  get { return p_eClass; }
  set
  {
    if (p_eClass != value)
    {
      p_eClass = value;
      OnPropertyChanged(nameof(SelectedClass));
    }
  }
}

最后绑定ComboBox视图(使用ValueConverterItemsSource绑定)...

<ComboBox ItemsSource="{Binding Path=SelectedClass, Converter={x:EnumToCollectionConverter}, Mode=OneTime}"
          SelectedValuePath="Value"
          DisplayMemberPath="Description"
          SelectedValue="{Binding Path=SelectedClass}" />

扫码关注云+社区