我想在ListView
中显示产品列表,其中一列是我要绑定的ComboBox
。这是我的枚举:
public enum SelectionMode { One, Two }
和产品类:
public class Product
{
public SelectionMode Mode { get; set; }
public string Name { get; set; }
}
在ViewModel
课程中,我有ObservableCollection
个Product
:
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
ListView
与ProductList
绑定:
<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>
我的问题是;将SelectedValue
类的ComboBox
SelectionMode
Product
属性绑定到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);
}
}
的属性的方法是什么?
更新
好。我在this topic找到了答案。所以我必须添加转换器类:
<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}}"/>
数据模板:
{{1}}
这就是全部。 希望它对其他人有用:)
答案 0 :(得分:4)
继承我对绑定枚举的使用到列表/ combox
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" />
我的视图模型
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调整来克服。我现在正在进行更改,一旦完成,我将更新此答案。
答案 1 :(得分:2)
如果您准备更改ComboBox的ItemsSource的绑定,那么只需SelectedValue="{Binding Mode,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
即可。
在这种情况下,您必须像这样绑定ItemsSource:ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ViewClass}}, Path=ModeList}"
;其中,ModeList是SelectionMode
类型列表的简单公共属性,包含应该在ComboBox下拉列表中显示的枚举,而ViewClass是此属性(ModeList)可用的类;确保在xaml中添加了名称空间的引用。
否则你必须使用转换器,它应该将字符串转换回枚举类型。
答案 2 :(得分:1)
我正在使用转换器,它还允许定义将显示的字符串而不是枚举值:http://www.ageektrapped.com/blog/the-missing-net-7-displaying-enums-in-wpf/