我想在 ListView
中显示产品列表,其中一列是我要绑定(bind)的 ComboBox
。这是我的枚举:
public enum SelectionMode { One, Two }
和产品类:
public class Product
{
public SelectionMode Mode { get; set; }
public string Name { get; set; }
}
在 ViewModel
类中,我有一个 Product
的 ObservableCollection
:
private ObservableCollection<Product> _productList;
public ObservableCollection<Product> ProductList
{
get
{
return _productList;
}
set
{
_productList = value;
}
}
public MainViewModel()
{
ProductList = new ObservableCollection<Product>
{
new Product {Mode = SelectionMode.One, Name = "One"},
new Product {Mode = SelectionMode.One, Name = "One"},
new Product {Mode = SelectionMode.Two, Name = "Two"}
};
}
最后我有一个 Grid
和一个绑定(bind)到我的 ProductList
的 ListView
:
<Window.Resources>
<ObjectDataProvider x:Key="AlignmentValues"
MethodName="GetNames" ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ViewModel:SelectionMode" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<Grid>
<ListView Height="120" HorizontalAlignment="Left"
VerticalAlignment="Top"
SelectionMode="Multiple"
ItemsSource="{Binding ProductList}" >
<ListView.View>
<GridView>
<GridViewColumn Width="120" Header="Product Name" DisplayMemberBinding="{Binding Path=Name}" />
<GridViewColumn Header="Selection Mode">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding Source={StaticResource AlignmentValues}}"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
我的问题是;将 ComboBox
的 SelectedValue
绑定(bind)到我的 Product
类的 SelectionMode
属性的方法是什么?
更新
嗯。我在 this topic 中找到了答案.所以我必须添加转换器类:
public class MyEnumToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return (SelectionMode)Enum.Parse(typeof(SelectionMode), value.ToString(), true);
}
}
并将其添加到窗口资源中:
<Window.Resources>
<ObjectDataProvider x:Key="AlignmentValues"
MethodName="GetNames" ObjectType="{x:Type System:Enum}">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="ViewModel:SelectionMode" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
<Converters:MyEnumToStringConverter x:Key="MyEnumConverter"/>
</Window.Resources>
最后编辑ComboBox
数据模板:
<ComboBox ItemsSource="{Binding Source={StaticResource AlignmentValues}}"
SelectedValue="{Binding Path=Mode, Converter={StaticResource MyEnumConverter}}"/>
就是这样。 希望它对其他人有用:)
最佳答案
这是我将枚举绑定(bind)到列表/组合框的用法
public enum EnumsAvailable
{
[Description("Its an A")]
a,
[Description("Its a B")]
b,
[Description("Its a C")]
c,
[Description("Its a D")]
d
} ;
这是我的 XAML
<ComboBox Grid.Column="4" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="cb_Application" VerticalAlignment="Top" Width="120"
ItemsSource="{Binding Path=ListOfEnumValues,Converter={converters:ArrayStringToEnumDescriptionConverter}}"
SelectedValue="{Binding Path=ChosenEnum,Converter={converters:DescriptionToEnumConverter},UpdateSourceTrigger=PropertyChanged}"
Validation.ErrorTemplate="{x:Null}" TabIndex="5" />
我的 View 模型
public EnumsAvailable ListOfEnumValues
{
get { return new EnumsAvailable(); }
}
public EnumsAvailable ChosenEnum {
get { return _ChosenEnum; }
set
{
if (_ChosenEnum != value)
{
_ChosenEnum = value;
RaisePropertyChanged(() => ChosenEnum);
}
}
}
和我的转换器
public class ArrayStringToEnumDescriptionConverter : BaseEnumDescriptionConverter, IValueConverter
{
public ArrayStringToEnumDescriptionConverter()
{
}
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var type = value.GetType();
return !type.IsEnum ? null : base.GetEnumDescription(type);
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
public abstract class BaseEnumDescriptionConverter : MarkupExtension
{
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
public IEnumerable<string> GetEnumDescription(Type destinationType)
{
var enumType = destinationType;
var values = RetrieveEnumDescriptionValues(enumType);
return new List<string>(values);
}
public object GetEnumFromDescription(string descToDecipher, Type destinationType)
{
var type = destinationType;
if (!type.IsEnum) throw new InvalidOperationException();
var staticFields = type.GetFields().Where(fld => fld.IsStatic);
foreach (var field in staticFields)
{
var attribute = Attribute.GetCustomAttribute(field,
typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attribute != null)
{
if (attribute.Description == descToDecipher)
{
return (Enum.Parse(type, field.Name, true));
}
}
else
{
if (field.Name == descToDecipher)
return field.GetValue(null);
}
}
throw new ArgumentException("Description is not found in enum list.");
}
public static string[] RetrieveEnumDescriptionValues(Type typeOfEnum)
{
var values = Enum.GetValues(typeOfEnum);
return (from object fieldInfo in values select DescriptionAttr(fieldInfo)).ToArray();
}
public static string DescriptionAttr(object enumToQuery)
{
FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
typeof(DescriptionAttribute), false);
return attributes.Length > 0 ? attributes[0].Description : enumToQuery.ToString();
}
public static string GetDomainNameAttribute(object enumToQuery)
{
FieldInfo fi = enumToQuery.GetType().GetField(enumToQuery.ToString());
DomainNameAttribute[] attributes = (DomainNameAttribute[])fi.GetCustomAttributes(
typeof(DomainNameAttribute), false);
return attributes.Length > 0 ? attributes[0].DomainName : enumToQuery.ToString();
}
}
public class DescriptionToEnumConverter : BaseEnumDescriptionConverter, IValueConverter
{
public DescriptionToEnumConverter(){}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var enumValue = value;
if (enumValue != null)
{
enumValue = GetEnumFromDescription(value.ToString(), targetType);
}
return enumValue;
}
}
在我个人看来,它更清洁且高度可重用。到目前为止,我发现的唯一缺陷是,如果您在代码中更新所选值(不是通过 UI),那么它不会在 UI 上更新。但这可以通过进一步调整 UI 来克服。我现在正在进行更改,完成后我会更新此答案。
关于c# - 将 ComboBox 的 SelectedValue 绑定(bind)到 WPF 中的枚举,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8644350/