带有本地化名称的 WPF ComboxBox 中的枚举

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29658721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 13:05:06  来源:igfitidea点击:

Enum in WPF ComboxBox with localized names

c#wpfmvvmenumslocalization

提问by juergen d

I have a ComboBox listing an Enum.

我有一个 ComboBox 列出了一个枚举。

enum StatusEnum {
    Open = 1, Closed = 2, InProgress = 3
}

<ComboBox ItemsSource="{Binding StatusList}"
          SelectedItem="{Binding SelectedStatus}" />

I want to display localized names for the enum values in English

我想用英语显示枚举值的本地化名称

Open
Closed
In Progress

but also in German (and other languages in the future)

但也有德语(以及未来的其他语言)

Offen
Geschlossen
In Arbeit

In my ViewModel using

在我的 ViewModel 中使用

public IEnumerable<StatusEnum> StatusList 
{
    get 
    {
        return Enum.GetValues(typeof(StatusEnum)).Cast<StatusEnum>();
    }
}

only gets me the names of the enum in the code and not the translated ones.

只让我得到代码中枚举的名称,而不是翻译后的名称。

I have general localization in place and can access them using i.e.

我有一般的本地化,可以使用 ie 访问它们

Resources.Strings.InProgress

which gets me the translation for the current language.

这让我得到了当前语言的翻译。

How can I bind the localization automatically?

如何自动绑定本地化?

回答by Yoh Deadfall

It's an example of the simple Enumto translated string converter.

这是一个简单Enum到翻译字符串转换器的例子。

public sealed class EnumToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
        { return null; }

        return Resources.ResourceManager.GetString(value.ToString());
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string str = (string)value;

        foreach (object enumValue in Enum.GetValues(targetType))
        {
            if (str == Resources.ResourceManager.GetString(enumValue.ToString()))
            { return enumValue; }
        }

        throw new ArgumentException(null, "value");
    }
}

Also you need a MarkupExtensionwhich will provide values:

您还需要一个MarkupExtension将提供值的:

public sealed class EnumerateExtension : MarkupExtension
{
    public Type Type { get; set; }

    public EnumerateExtension(Type type)
    {
        this.Type = type;
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        string[] names = Enum.GetNames(Type);
        string[] values = new string[names.Length];

        for (int i = 0; i < names.Length; i++)
        { values[i] = Resources.ResourceManager.GetString(names[i]); }

        return values;
    }
}

Usage:

用法:

<ComboBox ItemsSource="{local:Enumerate {x:Type local:StatusEnum}}"
          SelectedItem="{Binding SelectedStatus, Converter={StaticResource EnumToStringConverter}}" />

EDIT:You can make a more complex value converter and markup extension. The EnumToStringConvertercan use DescriptionAttribute's to get the translated strings. And the EnumerateExtensioncan use TypeConverter.GetStandardValues()and a converter. This allows to get standard values of the specified type (not only Enums) and convert them to strings or something another depending on the converter.

编辑:您可以制作更复杂的值转换器和标记扩展。在EnumToStringConverter可以使用DescriptionAttribute的,以获得翻译的字符串。并且EnumerateExtension可以使用TypeConverter.GetStandardValues()和转换器。这允许获取指定类型(不仅Enum是 s)的标准值,并将它们转换为字符串或其他取决于转换器的值。

Example:

例子:

<ComboBox ItemsSource="{local:Enumerate {x:Type sg:CultureInfo}, Converter={StaticResource CultureToNameConverter}}"
          SelectedItem="{Binding SelectedCulture, Converter={StaticResource CultureToNameConverter}}" />

EDIT:The more complex solution described above is published on GitHubnow.

编辑:上述更复杂的解决方案现已发布在GitHub 上

回答by Tseng

You can't, out of the box.

你不能,开箱即用。

But you can create an ObservableList<KeyValuePair<StatusEnum, string>>property and fill it with your enum/localized text and then bind it to your ComboBox.

但是您可以创建一个ObservableList<KeyValuePair<StatusEnum, string>>属性并用您的枚举/本地化文本填充它,然后将其绑定到您的ComboBox.

As for the string itself:

至于字符串本身:

var localizedText = (string)Application.Current.FindResource("YourEnumStringName");

Getting the Enum string representation with Enum.GetName/Enum.GetNamesmethods.

使用Enum.GetName/Enum.GetNames方法获取枚举字符串表示。

回答by Ayyappan Subramanian

You can do using a Attribute for the enum and writing an extension method for the enum. Refer the below code.

您可以为枚举使用属性并为枚举编写扩展方法。请参考以下代码。

<ComboBox Width="200" Height="25" ItemsSource="{Binding ComboSource}"
          DisplayMemberPath="Value"
          SelectedValuePath="Key"/>


public class MainViewModel
{
    public List<KeyValuePair<Status, string>> ComboSource { get; set; }

    public MainViewModel()
    {
        ComboSource = new List<KeyValuePair<Status, string>>();
        Status st=Status.Open;
        ComboSource = re.GetValuesForComboBox<Status>();
    }
}

public enum Status
{
    [Description("Open")]
    Open,
    [Description("Closed")]
    Closed,
    [Description("InProgress")]
    InProgress
}

 public static class ExtensionMethods
    {
        public static List<KeyValuePair<T, string>> GetValuesForComboBox<T>(this Enum theEnum)
        {
            List<KeyValuePair<T, string>> _comboBoxItemSource = null;
            if (_comboBoxItemSource == null)
            {
                _comboBoxItemSource = new List<KeyValuePair<T, string>>();
                foreach (T level in Enum.GetValues(typeof(T)))
                {
                    string Description = string.Empty;
                    FieldInfo fieldInfo = level.GetType().GetField(level.ToString());
                    DescriptionAttribute[] attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
                    if (attributes != null && attributes.Length > 0)
                    {
                        Description = GetDataFromResourceFile(attributes.FirstOrDefault().Description);
                    }
                    KeyValuePair<T, string> TypeKeyValue = new KeyValuePair<T, string>(level, Description);
                    _comboBoxItemSource.Add(TypeKeyValue);
                }
            }
            return _comboBoxItemSource;
        }

        public static string GetDataFromResourceFile(string key)
        {
            //Do you logic to get from resource file based on key for a language.
        }
    }

I have already posted a similar thing in SO Is it possible to databind to a Enum, and show user-friendly values?

我已经在 SO 中发布了类似的内容是否可以将数据绑定到枚举,并显示用户友好的值?