首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将ComboBoxes绑定到枚举。在银光里!

将ComboBoxes绑定到枚举。在银光里!
EN

Stack Overflow用户
提问于 2009-08-15 08:58:42
回答 4查看 28.3K关注 0票数 38

因此,对于如何将组合框绑定到WPF中的enum属性,web和StackOverflow有很多很好的答案。但是Silverlight缺少了使这一切成为可能的所有特性:例如:

  1. 您不能使用接受类型参数的通用EnumDisplayer-style IValueConverter,因为Silverlight不支持x:Type
  2. 您不能像在ObjectDataProvider中一样使用这种方法,因为Silverlight中不存在它。
  3. 由于Silverlight中不存在标记扩展,所以不能使用自定义标记扩展(如#2中的注释中的注释)。
  4. 您不能使用泛型而不是对象的Type属性来完成#1的版本,因为XAML不支持泛型(使它们工作的黑客都依赖于标记扩展,而Silverlight不支持)。

巨大的失败!

在我看来,做这件事的唯一方法就是

  1. 欺骗并绑定到我的ViewModel中的string属性,其setter/getter执行转换,使用视图中的代码隐藏将值加载到ComboBox中。
  2. 为我想要绑定的每个枚举创建一个自定义IValueConverter

是否有更通用的替代方案,即不需要为我想要的每个枚举一遍又一遍地编写相同的代码?我想我可以使用一个接受枚举作为类型参数的泛型类来执行解决方案#2,然后为我想要的每个枚举创建新的类,这些类很简单

代码语言:javascript
复制
class MyEnumConverter : GenericEnumConverter<MyEnum> {}

伙计们,你们有什么想法?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-08-15 09:44:15

啊,我说话太快了!有一个非常好的解决方案,至少在Silverlight 3中。(它可能只在3中,因为这条线表示与此相关的bug在Silverlight 3中修复了。)

基本上,您需要ItemsSource属性的单个转换器,但它可以是完全通用的,而不需要使用任何禁止的方法,只要您将类型为MyEnum的属性的名称传递给它。而且,绑定到SelectedItem是完全没有痛苦的,不需要转换器!嗯,至少只要你不想通过DescriptionAttribute为每个枚举值定制字符串,嗯.可能需要另一个转换器;希望我能把它变成通用的。

更新:我做了一个转换器,它工作!遗憾的是,我现在不得不绑定到SelectedIndex,但没关系。利用这些人:

代码语言:javascript
复制
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)
        {
            // Note: as pointed out by Martin in the comments on this answer, this line
            // depends on the enum values being sequentially ordered from 0 onward,
            // since combobox indices are done that way. A more general solution would
            // probably look up where in the GetValues array our value variable
            // appears, then return that index.
            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:

代码语言:javascript
复制
<ComboBox x:Name="MonsterGroupRole"
          ItemsSource="{Binding MonsterGroupRole,
                                Mode=OneTime,
                                Converter={StaticResource EnumToIEnumerableConverter}}"
          SelectedIndex="{Binding MonsterGroupRole,
                                  Mode=TwoWay,
                                  Converter={StaticResource EnumToIntConverter}}" />

这类资源声明XAML:

代码语言:javascript
复制
<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会慢一些,所以我应该考虑使用缓存吗?

票数 34
EN

Stack Overflow用户

发布于 2010-05-10 18:50:59

还有一种方法可以将ComboBox绑定到枚举,而不需要对所选项使用自定义转换器。你可以在

http://charlass.wordpress.com/2009/07/29/binding-enums-to-a-combobbox-in-silverlight/

它不使用DescriptionAttributes..。但是它非常适合我,所以我想这取决于它将被使用的场景。

票数 4
EN

Stack Overflow用户

发布于 2012-11-30 18:00:22

我发现简单的封装枚举数据要容易得多。

代码语言:javascript
复制
public ReadOnly property MonsterGroupRole as list(of string)
  get
    return [Enum].GetNames(GetType(GroupRoleEnum)).Tolist
  End get
End Property

private _monsterEnum as GroupRoleEnum
Public Property MonsterGroupRoleValue as Integer
  get
    return _monsterEnum
  End get
  set(value as integer)
    _monsterEnum=value
  End set
End Property

..。

代码语言:javascript
复制
<ComboBox x:Name="MonsterGroupRole"
      ItemsSource="{Binding MonsterGroupRole,
                            Mode=OneTime}"
      SelectedIndex="{Binding MonsterGroupRoleValue ,
                              Mode=TwoWay}" />

这将完全消除转换器的需要.:)

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1281490

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档