2010-11-22 2 views
1

У меня есть простой ComboBox, который имеет несколько простых значений. Я пытаюсь сделать привязку с двумя способами привязки к свойству enum на моей модели.WPF ComboBox 2-Way Binding

<ComboBox d:LayoutOverrides="Height" Grid.Column="1" SelectedItem="{Binding SortType, Converter={StaticResource sortSelect}, Mode=TwoWay}"> 
     <ListBoxItem Content="Ascending" Tag="Ascending"/> 
     <ListBoxItem Content="Descending" Tag="Descending"/> 
     <ListBoxItem Content="Absolute Ascending" Tag="AbsoluteAscending"/> 
     <ListBoxItem Content="Absolute Descending" Tag="AbsoluteDescending" /> 
    </ComboBox> 

Вот мой ValueConverter

public class RdiSortMatchConverter : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     var val = (RdiSort) value; 
     switch (val) 
     { 
      case RdiSort.Ascending: 
       return "Ascending"; 
      case RdiSort.Descending: 
       return "Descending"; 
      case RdiSort.AbsoluteAscending: 
       return "Absolute Ascending"; 
      case RdiSort.AbsoluteDescending: 
       return "Absolute Descending"; 
      default: 
       throw new ArgumentOutOfRangeException(); 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return (RdiSort) Enum.Parse(typeof (RdiSort), (string) ((ListBoxItem) value).Tag); 
    } 
} 

Метод ConvertBack работает отлично, и обновляет моя модель, основанная на значении Tag в ListBoxItem, но я не могу получить начальное Enum значение для выбора правильного ListBoxItem

Каков наилучший способ достижения этого, или есть лучший способ привязки t Enums (учтите, что мне нужен пользовательский d для каждого значения Enum.

+0

Смотрите этот вопрос: [Databinding свойство перечисления в ComboBox в WPF] (http://stackoverflow.com/questions/58743/databinding-an-enum-property-to-a-combobox-in-wpf) –

ответ

2

Вы можете сделать это вот так. Сначала добавьте описание для каждого из ваших Enum значения

public enum RdiSort 
{ 
    [Description("Ascending Description")] 
    Ascending, 
    [Description("Descending Description")] 
    Descending, 
    [Description("AbsoluteAscending Description")] 
    AbsoluteAscending, 
    [Description("AbsoluteDescending Description")] 
    AbsoluteDescending 
} 

Затем с помощью ObjectDataProvider для ComboBox

xmlns:sys="clr-namespace:System;assembly=mscorlib" 
xmlns:MyEnumerations="clr-namespace:MyEnumerations" 

<ObjectDataProvider MethodName="GetValues" 
        ObjectType="{x:Type sys:Enum}" 
        x:Key="RdiSortValues"> 
    <ObjectDataProvider.MethodParameters> 
     <x:Type TypeName="MyEnumerations:RdiSort" /> 
    </ObjectDataProvider.MethodParameters> 
</ObjectDataProvider> 

Используйте поставщик RdiSortValues ​​в вашем ComboBox и создать DataTemplate с TextBlock и конвертер, чтобы увидеть Описание вместо значения Enum.

<local:EnumDescriptionConverter x:Key="EnumDescriptionConverter"/> 

<ComboBox SelectedItem="{Binding SortType}" 
      ItemsSource="{Binding Source={StaticResource RdiSortValues}}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
      <TextBlock Text="{Binding Converter={StaticResource EnumDescriptionConverter}}"/> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

И, наконец, преобразователь. В ConvertBack нет необходимости, поскольку конвертер используется только в TextBlock для отображения.

public class EnumDescriptionConverter : IValueConverter 
{ 
    private string GetEnumDescription(Enum enumObj) 
    { 
     FieldInfo fieldInfo = enumObj.GetType().GetField(enumObj.ToString()); 
     object[] attribArray = fieldInfo.GetCustomAttributes(false); 
     if (attribArray.Length == 0) 
     { 
      return enumObj.ToString(); 
     } 
     else 
     { 
      DescriptionAttribute attrib = attribArray[0] as DescriptionAttribute; 
      return attrib.Description; 
     } 
    } 

    object IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     if (value != null) 
     { 
      RdiSort myEnum = (RdiSort)value; 
      string description = GetEnumDescription(myEnum); 
      return description; 
     } 
     return null; 
    } 
    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 
    { 
     return string.Empty; 
    } 
} 
0

Вот решение, которое я сделал.

.xaml =>

<UserControl.Resources> 
    <c:PriorityConvertor x:Key="priorityConvertor"></c:PriorityConvertor> 
</UserControl.Resources> 

.cs файл =>

public class PriorityConvertor : IValueConverter 
{ 

    #region IValueConverter Members 

    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (value == null) 
     { 
      return string.Empty; 
     } 
     if (value.ToString() == "1") 
     { 
      return "High"; 
     } 
     else if (value.ToString() == "2") 
     { 
      return "Medium"; 
     } 
     else if (value.ToString() == "3") 
     { 
      return "Low"; 
     } 
     return "Low"; 
    } 

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 

    #endregion 
} 

}