2016-05-19 4 views
1

Eigentlich mit Ich bin der Lage, meine Combobox an eine Enum zu binden ihre DescriptionAttribute:Bindung Combobox an eine Enumeration, mit Ausnahme einer Enum-Element

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

I this SO answer

Meine Enum verwendet habe, ist:

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 
} 

ich brauche die AlternativeToSecondEnumMember zu verstecken, weil es irrelevant ist es in der ComboBox zu sehen.

Um dies zu tun, was ist die beste Lösung? Vielleicht ein Converter oder setzen Sie die ItemsSource in Code hinter?

+0

Was ist mit dem ObjectDataProvider? Hast du diesen Weg versucht? – Ilan

+0

@Ilan versuchte nicht, wie würdest du tun? – ZwoRmi

+0

Ich habe eine Lösung hinzugefügt. Lassen Sie mich wissen, wenn Sie eine Klarstellungen wünschen – Ilan

Antwort

2

Ich würde vorschlagen, eine einfache Lösung zu verwenden, um Ihr Leben einfacher zu machen. Angenommen, Sie verwenden MVVM, können Sie einfach eine neue Eigenschaft erstellen, die die Liste der geeigneten Werte enthält.

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; 
    } 
} 

Persönlich finde ich, dass es keinen Sinn, bei dem Versuch, einen Weg zu finden, den Enum Typ in eine Liste von String-Werte automatisch zu konvertieren, wenn nicht alle Werte in der Enum gültig sind.

+0

Wenn ich dies tun, muss ich _string_ zu "MyEnum" in meiner VM _convert_, das ist, was ich vermeiden will. – ZwoRmi

0

Ich war in der Lage, einen Weg zu finden, was ich will mit einem Converter und DataTrigger von this solution. Da der Link etwa IsEnabled und nicht IsVisible ist, und für die Lesbarkeit, legte ich hier, was für mich funktionierte.

Zuerst hatte ich einen DataTrigger in hinzufügen meine ComboBox:

<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> 

Dann ein ComboBoxVisibleConverter zu erstellen:

class ComboBoxVisibleConverter :IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     EnumerationExtension.EnumerationMember enumerationMember = value as EnumerationExtension.EnumerationMember; 
     if (enumerationMember == null) 
      return null; 
     if ((MyEnum)enumerationMember.Value == MyEnum.AlternativeToSecondEnumMember) 
      return true; //The DataTrigger will collapse the ComboBoxItem because of the Value="true" 
     return false; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     throw new NotSupportedException(); 
    } 
} 

Die EnumerationExtension ist here

1

Hier einige Attribut basiert Lösung, verwendete die spezielle Implementierung von ObjectDataProvider. Wenn also ein Enum-Feld durch das ShouldBeHiddenAttribute dekoriert wird und sein Wert true ist, wird das enum-Feld in der UI (ComboBox) verborgen.

ShouldBeHiddenAttribute Code

/// <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; } 
} 

Ihre Enum mit meinem Attribut dekoriert

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 
} 

Sonderobject Implementierung

/// <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 Object Definition

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

Combo Bindungs ​​

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

Grüßen.