C# 将Combobox绑定到枚举(一个枚举元素除外)

C# 将Combobox绑定到枚举(一个枚举元素除外),c#,wpf,binding,combobox,enums,C#,Wpf,Binding,Combobox,Enums,实际上,我可以使用描述属性将我的组合框绑定到枚举: <ComboBox ItemsSource="{Binding Source={extension:Enumeration {x:Type model:MyEnum}}}" DisplayMemberPath="Description" SelectedValue="{Binding Path=DataContextEnumProp}" SelectedValuePath="Value"/>

实际上,我可以使用
描述属性将我的
组合框
绑定到
枚举

<ComboBox ItemsSource="{Binding Source={extension:Enumeration {x:Type model:MyEnum}}}"
      DisplayMemberPath="Description" 
      SelectedValue="{Binding Path=DataContextEnumProp}"
      SelectedValuePath="Value"/>
我需要隐藏
AlternativeToSecondEnumMember
,因为在
组合框中查看它与此无关


要做到这一点,最好的解决方案是什么?也许是一个
转换器
或者在代码隐藏中设置
项资源

我建议使用一个简单的解决方案,让你的生活更轻松。假设您使用的是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;
    }
}
private observedcollection\u myeumlist;
公共可观测收集脊髓学家
{
得到
{
if(this.\u myEnumList==null)
{
字符串[]myList=Enum.GetNames(typeof(MyEnum));
//您还可以使用自己的逻辑生成列表
这._myEnumList=新的可观察集合(myList);
}
把这个还给我;
}
}

就我个人而言,当
Enum
中的值并非全部有效时,试图找到一种将
Enum
类型自动转换为字符串值列表的方法是没有意义的。

我能够找到一种方法,使用
转换器和
数据触发器来实现我想要的功能。由于链接是关于
IsEnabled
,而不是
IsVisible
,为了可读性,我把对我有用的东西放在这里

首先,我必须在我的组合框中添加一个
DataTrigger

<ComboBox ItemsSource="{Binding Source={extension:Enumeration {x:Type model:MyEnum}}}" 
          DisplayMemberPath="Description" 
          SelectedValue="{Binding Path=DataContextEnumProp}" 
          SelectedValuePath="Value">
    <ComboBox.ItemContainerStyle>
        <Style TargetType="ComboBoxItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Content, RelativeSource={RelativeSource Self}, 
                             Converter={StaticResource ComboBoxVisibleConverter}}" Value="true">
                    <Setter Property="Visibility" Value="Collapsed"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ComboBox.ItemContainerStyle>
</ComboBox>

EnumerationExtension
是以下是一些使用ObjectDataProvider特殊实现的基于属性的解决方案。因此,如果一个枚举字段由ShouldBeHiddenAttribute修饰并且其值为true,那么该枚举字段将隐藏在UI(组合框)中

应避免属性代码

/// <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
}
特殊对象数据提供程序实现

/// <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;
    }
}
    <ObjectDataProvider x:Key="MyEnumMembers" MethodName="GetShortListOfApplicationGestures" ObjectType="{x:Type pageBasedApp:AttributeBasedObjectDataProvider}">
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="pageBasedApp:MyEnum" />
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>
//
///帮助根据装饰属性显示值
/// 
公共类AttributeBaseObjectDataProvider:ObjectDataProvider
{
/// 
///根据枚举的两个属性返回枚举的值
///1.DescriptionAttribute-提供枚举值的显示名称
///2.ShouldBeHiddenAttribute-提供枚举的dispaly状态
/// 
///枚举字段值
///如果ShouldBeHiddenAttribute.HiddenInUi值为true,则如果已定义,则返回null,否则返回枚举说明(或未定义枚举实际值id说明)
公共对象GetEnumValues(枚举enumObj)
{
//获取ShouldBeHiddenAttribute值
var isHidden=enumObj.GetType().GetRuntimeField(enumObj.ToString())。
GetCustomAttributes(typeof(ShouldBeHiddenAttribute),false)。
SingleOrDefault()作为应指定的属性;
if(isHidden!=null&&isHidden.HiddenInUi)返回null;
//获取DescriptionAttribute值
var attribute=enumObj.GetType().GetRuntimeField(enumObj.ToString())。
GetCustomAttributes(typeof(DescriptionAttribute),false)。
SingleOrDefault()作为DescriptionAttribute;
return attribute==null?enumObj.ToString():attribute.Description;
}
/// 
///返回枚举值的集合
/// 
///枚举类型
///枚举值的集合
public List GetShortListofApplication测试(类型)
{
var应用程序测试短列表=
GetValues(type).OfType().Select(GetEnumValues).Where(o=>o!=null).ToList();
返回
应用测试的短名单;
}
}
Xaml 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;
    }
}
    <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"/>


注意。

既然您编写了要避免在VM中将
string
转换为
MyEnum
,下面是一个没有
string
的解决方案:

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

通过这种方式,您可以继续使用MyEnum,无需进行字符串转换。

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

    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;
    }
公共静态IList ToList(此类型,Enum[]valuesToSkip)
{
ArrayList enumList=新建ArrayList();
数组enumValues=Enum.GetValues(类型);
foreach(枚举值中的枚举值)
{
if(值跳过.包含(值))
继续;
//在这个解决方案中,我有一个从枚举中获取描述的方法
//但您可以避免这一部分,并用枚举值填充列表
//添加(新的KeyValuePair(value,GetEnumDescription(value));
枚举列表。添加(值);
}
退货清单;
}
我已经编写了自己的ToList方法,该方法返回枚举,不包括我通过valuesToSkip传递的枚举。 我以以下方式填充组合框:


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

如果这样做,我必须在我的VM中将
string
转换为
MyEnum
,这就是我想要避免的。@ZwoRmi
observeCollection MyEnumList=new observeCollection(Enum.GetValues(typeof(MyEnum)).Cast()ObjectDataProvider呢?你试过这种方法吗?@Ilan没有试过,你会怎么做?我已经添加了一些解决方案。如果您需要澄清,请告诉我