是否可以使用ObjectDataProvider方法将ListBox绑定到枚举,并以某种方式设置样式以显示描述attriibute?如果是这样,怎么会这样做......?
答案 0 :(得分:87)
是的,有可能。这样做。假设我们有枚举
public enum MyEnum
{
[Description("MyEnum1 Description")]
MyEnum1,
[Description("MyEnum2 Description")]
MyEnum2,
[Description("MyEnum3 Description")]
MyEnum3
}
然后我们可以将ObjectDataProvider用作
xmlns:MyEnumerations="clr-namespace:MyEnumerations"
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type sys:Enum}"
x:Key="MyEnumValues">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="MyEnumerations:MyEnum" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
对于ListBox,我们将ItemsSource设置为MyEnumValues并将ItemTemplate应用于Converter。
<ListBox Name="c_myListBox" SelectedIndex="0" Margin="8"
ItemsSource="{Binding Source={StaticResource MyEnumValues}}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource EnumDescriptionConverter}}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
在转换器中我们得到描述并将其返回
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)
{
Enum myEnum = (Enum)value;
string description = GetEnumDescription(myEnum);
return description;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return string.Empty;
}
}
GetEnumDescription方法可能应该去其他地方,但你明白了这一点:)
答案 1 :(得分:2)
如果绑定到Enum,您可以通过IValueConverter将其转换为描述。
有关如何完成此操作的说明,请参阅Binding ComboBoxes to enums... in Silverlight!。
有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx。
答案 2 :(得分:2)
另一种解决方案是自定义MarkupExtension,该自定义类型会从枚举类型生成项。这使xaml更加紧凑和可读。
using System.ComponentModel;
namespace EnumDemo
{
public enum Numbers
{
[Description("1")]
One,
[Description("2")]
Two,
Three,
}
}
用法示例:
<Window x:Class="EnumDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:EnumDemo">
<ListBox ItemsSource="{local:EnumToCollection EnumType={x:Type local:Numbers}}"/>
</Window>
MarkupExtension实现
using System;
using System.ComponentModel;
using System.Linq;
using System.Windows.Markup;
namespace EnumDemo
{
public class EnumToCollectionExtension : MarkupExtension
{
public Type EnumType { get; set; }
public override object ProvideValue(IServiceProvider serviceProvider)
{
if (EnumType == null) throw new ArgumentNullException(nameof(EnumType));
return Enum.GetValues(EnumType).Cast<Enum>().Select(EnumToDescriptionOrString);
}
private string EnumToDescriptionOrString(Enum value)
{
return value.GetType().GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.Cast<DescriptionAttribute>()
.FirstOrDefault()?.Description ?? value.ToString();
}
}
}
答案 3 :(得分:1)
您可以在项目中定义一个资源文件(* .resx文件)。在此文件中,您必须定义&#34;键值对&#34;,如下所示:
"YellowCars" : "Yellow Cars",
"RedCars" : "Red Cars",
依旧......
键等于你的枚举条目,如下所示:
public enum CarColors
{
YellowCars,
RedCars
}
依旧......
使用WPF时,可以在XAML-Code中实现,如下所示:
<ComboBox ItemsSource="{Binding Source={StaticResource CarColors}}" SelectedValue="{Binding CarColor, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource CarColorConverter}}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
然后你必须编写你的转换器,如下所示:
using System;
using System.Globalization;
using System.Resources;
using System.Windows.Data;
public class CarColorConverter : IValueConverter
{
private static ResourceManager CarColors = new ResourceManager(typeof(Properties.CarColors));
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var key = ((Enum)value).ToString();
var result = CarColors.GetString(key);
if (result == null) {
result = key;
}
return result;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
我的回答是7年到晚;-)但也许它可以被其他人使用!
答案 4 :(得分:0)
是的,可能。
ListBox
可以帮助我们做到这一点,而无需使用转换器。
此方法的步骤如下:
创建一个ListBox并将该Listbox的ItemsSource设置为枚举,并将ListBox的SelectedItem绑定到selected属性。
然后将创建每个ListBoxItem。
public enum EnumValueNames
{
EnumValueName1,
EnumValueName2,
EnumValueName3
}
然后将以下属性添加到您的DataContext(或MVVM的ViewModel)中,该属性记录了选中的选中项。
public EnumValueNames SelectedEnumValueName { get; set; }
<Window.Resources>
<ObjectDataProvider MethodName="GetValues"
ObjectType="{x:Type system:Enum}"
x:Key="EnumValueNames">
<ObjectDataProvider.MethodParameters>
<x:Type TypeName="local:EnumValueNames" />
</ObjectDataProvider.MethodParameters>
</ObjectDataProvider>
</Window.Resources>
<ListBox ItemsSource="{Binding Source={StaticResource EnumValueNames}}"
SelectedItem="{Binding SelectedEnumValueName, Mode=TwoWay}" />
参考: https://www.codeproject.com/Articles/130137/Binding-TextBlock-ListBox-RadioButtons-to-Enums