将Combobox绑定到枚举,除了一个枚举元素

时间:2016-05-19 06:39:05

标签: c# wpf binding combobox enums

实际上,我可以使用ComboboxEnum绑定到DescriptionAttribute

<ComboBox ItemsSource="{Binding Source={extension:Enumeration {x:Type model:MyEnum}}}"
      DisplayMemberPath="Description" 
      SelectedValue="{Binding Path=DataContextEnumProp}"
      SelectedValuePath="Value"/>

我使用了this SO answer

我的枚举是:

public enum MyEnum
{
    [XmlEnum("first")]
    [Description("first")]
    FirstEnumMember,

    [XmlEnum("second")]
    [Description("second")]
    SecondEnumMember,

    //[XmlIgnore]
    [Description("second")]
    AlternativeToSecondEnumMember //I don't want this one to be in the combobox
}

我需要隐藏AlternativeToSecondEnumMember,因为在ComboBox中看到它是无关紧要的。

要做到这一点,最好的解决方案是什么?可能是Converter或在代码中设置ItemsSource吗?

5 个答案:

答案 0 :(得分:3)

这是一些使用ObjectDataProvider特殊实现的基于属性的解决方案。因此,如果Enum字段由ShouldBeHiddenAttribute修饰且其值为true,则枚举字段将隐藏在UI(ComboBox)中。

ShouldBeHiddenAttribute代码

/// <summary>
/// helps to hide the enum value
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
public class ShouldBeHiddenAttribute : Attribute
{
    public ShouldBeHiddenAttribute(bool isHiddenInUi)
    {
        HiddenInUi = isHiddenInUi;
    }

    public bool HiddenInUi { get; set; }
}

您的枚举装饰了我的属性

public enum MyEnum
{
    [XmlEnum("first")]
    [Description("first")]
    FirstEnumMember,

    [XmlEnum("second")]
    [Description("second")]
    SecondEnumMember,

    //[XmlIgnore]
    [Description("second")]
    [ShouldBeHiddenAttribute(true)]
    AlternativeToSecondEnumMember
    //I don't want this one to be in the combobox
}

特殊ObjectDataProvider实施

/// <summary>
/// helps to display value according to decorating attributes
/// </summary>
public class AttributeBasedObjectDataProvider : ObjectDataProvider
{
    /// <summary>
    /// returns value of enum according its two attributes
    /// 1. DescriptionAttribute - provide a dispaly name of the enum value
    /// 2. ShouldBeHiddenAttribute - provide a dispaly state of the enum
    /// </summary>
    /// <param name="enumObj">enum field value</param>
    /// <returns>if ShouldBeHiddenAttribute.HiddenInUi value is true return null else enum Description if defined(or enum actual value id Description is not defined)</returns>
    public object GetEnumValues(Enum enumObj)
    {
        //get the ShouldBeHiddenAttribute value
        var isHidden = enumObj.GetType().GetRuntimeField(enumObj.ToString()).
            GetCustomAttributes(typeof (ShouldBeHiddenAttribute), false).
            SingleOrDefault() as ShouldBeHiddenAttribute;
        if (isHidden != null && isHidden.HiddenInUi) return null;
        //get the DescriptionAttribute value
        var attribute = enumObj.GetType().GetRuntimeField(enumObj.ToString()).
            GetCustomAttributes(typeof (DescriptionAttribute), false).
            SingleOrDefault() as DescriptionAttribute;
        return attribute == null ? enumObj.ToString() : attribute.Description;
    }

    /// <summary>
    /// returns collection of enum values
    /// </summary>
    /// <param name="type">enum type</param>
    /// <returns>collection of enum values</returns>
    public List<object> GetShortListOfApplicationGestures(Type type)
    {
        var shortListOfApplicationGestures =
            Enum.GetValues(type).OfType<Enum>().Select(GetEnumValues).Where(o => o != null).ToList();
        return
            shortListOfApplicationGestures;
    }
}

Xaml ObjectDataProvider定义

    <ObjectDataProvider x:Key="MyEnumMembers" MethodName="GetShortListOfApplicationGestures" ObjectType="{x:Type pageBasedApp:AttributeBasedObjectDataProvider}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="pageBasedApp:MyEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

组合绑定

<ComboBox ItemsSource="{Binding Source={StaticResource MyEnumMembers}}" Width="150"/>

问候。

答案 1 :(得分:2)

我建议使用简单的解决方案让您的生活更轻松。假设您正在使用MVVM,您只需创建一个新属性来保存合适值的列表。

private ObservableCollection<string> _myEnumList;
public ObservableCollection<string> MyEnumList
{
    get
    {
        if (this._myEnumList == null)
        {
            string[] myList = Enum.GetNames(typeof(MyEnum));
            // You can also use your own logic to generate your list


            this._myEnumList = new ObservableCollection<string>(myList);
        }
        return this._myEnumList;
    }
}

我个人认为,当Enum中的所有值都无效时,尝试找到将Enum类型自动转换为字符串值列表的方法毫无意义。< / p>

答案 2 :(得分:0)

我能够使用this solution中的"(A,B,C)"key = db.Key.from_path('Model', int(id)) 找到一种方法来做我想做的事情。由于链接大约是obj = db.get(key) 而不是<div class="input-field col s12 m12 l12"> <input id="birthdate" type="date" class="datepicker" name="birthdate"> <label for="birthdate">Birthdate</label> </div> <div id="birthdate-icon" class="cursor-pointer"> <i class="material-icons">today</i> </div> ,为了便于阅读,我在这里提出了对我有用的内容。

首先,我必须在$(document).ready(function(){ $('.datepicker').pickadate({ selectMonths: true, selectYears: 150, format: 'yyyy-mm-dd', min: new Date(1900,1,1), max: true }); initBindings(); }); function initBindings(){ $('#birthdate-icon').click(function(){ $('#birthdate').click(); }); } 中添加Converter

DataTrigger

然后创建IsEnabled

IsVisible

DataTriggerhere

答案 3 :(得分:0)

由于您曾经写过要避免在VM中将string转换为MyEnum的情况,因此这里是一种没有string的解决方案:

public ObservableCollection<MyEnum> MyEnumList { get; } = new ObservableCollection<MyEnum>(
    Enum.GetValues(typeof(MyEnum)).
    Cast<MyEnum>().
    Where(myEnum => myEnum != MyEnum.AlternativeToSecondEnumMember));

通过这种方式,您可以继续使用MyEnum,而无需进行string的转换。

答案 4 :(得分:0)

这就是我找到的解决方案:

    public static IList ToList(this Type type, Enum[] valuesToSkip)
    {
        ArrayList enumList = new ArrayList();
        Array enumValues = Enum.GetValues(type);

        foreach (Enum value in enumValues)
        {
            if (valuesToSkip.Contains(value))
                continue;

            // in this solution I had a method to get the description from the Enum
            // but you can avoid this part and populate your list with the enum values
            //enumList.Add(new KeyValuePair<Enum, string>(value, GetEnumDescription(value)));
              enumList.Add(value);
        }

        return list;
    }

我已经编写了自己的ToList方法,该方法可以返回枚举,但不包括我通过valuesToSkip传递的枚举。 我以这种方式填充组合框:

comboBox.DataSource = EnumExtension.ToList(typeof(yourEnum),新的Enum [] {yourEnum.ValueToSkip});