Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WPF将列表框绑定到枚举,显示Description属性_C#_Wpf_Data Binding_Enums_Listbox - Fatal编程技术网

C# WPF将列表框绑定到枚举,显示Description属性

C# WPF将列表框绑定到枚举,显示Description属性,c#,wpf,data-binding,enums,listbox,C#,Wpf,Data Binding,Enums,Listbox,是否可以使用ObjectDataProvider方法将列表框绑定到枚举,并以某种方式设置其样式以显示描述属性?如果是这样的话,我们将如何进行此操作…?如果绑定到枚举,您可能会通过IValueConverter将其转换为描述 有关如何完成此操作的说明,请参阅 有关更多信息,请参阅。是的,这是可能的。这就行了。假设我们有枚举 public enum MyEnum { [Description("MyEnum1 Description")] MyEnum1, [Descript

是否可以使用ObjectDataProvider方法将列表框绑定到枚举,并以某种方式设置其样式以显示描述属性?如果是这样的话,我们将如何进行此操作…?

如果绑定到枚举,您可能会通过IValueConverter将其转换为描述

有关如何完成此操作的说明,请参阅


有关更多信息,请参阅。

是的,这是可能的。这就行了。假设我们有枚举

public enum MyEnum
{
    [Description("MyEnum1 Description")]
    MyEnum1,
    [Description("MyEnum2 Description")]
    MyEnum2,
    [Description("MyEnum3 Description")]
    MyEnum3
}
然后我们可以将ObjectDataProvider用作

xmlns:MyEnumerations=“clr命名空间:MyEnumerations”

对于ListBox,我们将ItemsSource设置为MyEnumValues,并使用转换器应用ItemTemplate


在转换器中,我们得到描述并返回它

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方法可能应该放在其他地方,但您会想到:)


选中。

您可以在项目(*.resx文件)中定义ressource文件。在此文件中,您必须定义“键值对”,如下所示:

"YellowCars" : "Yellow Cars",
"RedCars" : "Red Cars",
public enum CarColors
{
    YellowCars,
    RedCars
}
<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();
    }
}
等等

键与您的枚举项相等,如下所示:

"YellowCars" : "Yellow Cars",
"RedCars" : "Red Cars",
public enum CarColors
{
    YellowCars,
    RedCars
}
<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();
    }
}
等等

使用WPF时,可以在XAML代码中实现,如下所示:

"YellowCars" : "Yellow Cars",
"RedCars" : "Red Cars",
public enum CarColors
{
    YellowCars,
    RedCars
}
<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年;-)但也许它可以被其他人使用

另一个解决方案将是一个从枚举类型生成项的自定义方法。这使得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();
        }
    }
}
使用系统;
使用系统组件模型;
使用System.Linq;
使用System.Windows.Markup;
命名空间枚举演示
{
公共类EnumToCollectionExtension:MarkupExtension
{
公共类型EnumType{get;set;}
公共覆盖对象ProviderValue(IServiceProvider服务提供程序)
{
如果(EnumType==null)抛出新的ArgumentNullException(nameof(EnumType));
返回Enum.GetValues(EnumType).Cast().Select(EnumToDescriptionOrString);
}
私有字符串EnumToDescriptionOrString(枚举值)
{
返回值.GetType().GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute),false)
.Cast()
.FirstOrDefault()?.Description??value.ToString();
}
}
}
是的,有可能

ListBox
可以帮助我们做到这一点,而无需转换器

此方法的步骤如下:
创建一个ListBox并将ListBox的ItemsSource设置为枚举,并将ListBox的SelectedItem绑定到selected属性

然后将创建每个ListBoxItem

  • 步骤1:定义枚举
公共枚举EnumValueName
{ 
枚举值名称1,
枚举值名称2,
枚举值名称3
}
然后将以下属性添加到DataContext(或MVVM的ViewModel)中,该属性记录选中的项目

公共EnumValueNames SelectedEnumValueName{get;set;}
  • 步骤2:将枚举添加到窗口、用户控件或网格等的静态资源中

  • 步骤3:使用列表框填充每个项目

参考文献:

可能是的副本。谢谢,现在将尝试:)喜欢它,干掉它。我使用了一个小linq来配对GetEnumDescription,您可以在这里设置它,这样您就必须为每种类型的enum创建一个转换器?请注意,您必须创建一个转换器实例作为ressource,例如:
如果您在枚举上有不同的属性,这将中断-我建议将代码更改为attrib=attribArray.OfType().FirstOrDefault();检查null,因为它更健壮。这比最上面的答案更简单。我只是有个问题。当我绑定到存储枚举的属性时,它会正确更新,但在加载窗口时不会自动显示值。你知道我怎么解决这个问题吗?@EatATaco你在用组合框吗?如果是,请看这里: