WPF ComboBox 中具有本地化名称的枚举

Enum in WPF ComboxBox with localized names

我有一个列出枚举的 ComboBox。

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

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

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

Open
Closed
In Progress

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

Offen
Geschlossen
In Arbeit

在我的 ViewModel 中使用

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

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

我已经进行了一般本地化,可以使用

访问它们
Resources.Strings.InProgress

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

如何自动绑定本地化?

你不能,开箱即用。

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

至于字符串本身:

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

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

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

<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.
        }
    }

我已经在 SO Is it possible to databind to a Enum, and show user-friendly values?

中发布了类似的内容

这是一个简单的 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");
    }
}

您还需要一个 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;
    }
}

用法:

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

编辑: 您可以创建更复杂的值转换器和标记扩展。 EnumToStringConverter 可以使用 DescriptionAttribute 来获取翻译后的字符串。而 EnumerateExtension 可以使用 TypeConverter.GetStandardValues() 和转换器。这允许获取指定类型的标准值(不仅是 Enums)并根据转换器将它们转换为字符串或其他内容。

示例:

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

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