2

我正在ListPicker从一个Enum. 例如,如果我有以下枚举:

public enum Pets 
{
    Dog,
    Cat,
    Platypus 
}

我通过以下方式填充 ListPicker:

PetListPicker.ItemsSource = Enum.GetValues(typeof(Pets));

一切都好,直到那里。我的 ListPicker 控件显示要选择的项目的名称。

问题是我想本地化 Enum 项目以用不同的语言使用它们。也就是说,我希望 ListPicker 以应用程序当前使用的语言显示名称。

我在资源文件中有本地化字符串,我用它来本地化应用程序的其余部分。但是,我不知道如何使它与 ListPicker 项目一起使用。

4

3 回答 3

7

我终于找到了一种方法来实现我的目标,使用Description枚举值的属性和Converter.

由于无法将资源文件中的值直接用作描述属性,因此我首先创建了自定义的 LocalizedDescriptionAttribute 类,该类继承自 DescriptionAttribute:

public class LocalizedDescriptionAttribute : DescriptionAttribute
{
    public LocalizedDescriptionAttribute(string resourceId)
        : base(GetStringFromResource(resourceId))
    { }

    private static string GetStringFromResource(string resourceId)
    {
        return AppResources.ResourceManager.GetString(resourceId);
    }
}

这样我就可以使用资源的 ID 作为 LocalizedDescription 属性:

public enum Pet
{
    [LocalizedDescription("Dog")]
    Dog,
    [LocalizedDescription("Cat")]
    Cat,
    [LocalizedDescription("Platypus")]
    Platypus 
}

在这里,我创建了一个ValueConverter在我的 ListPicker 中以适当语言显示字符串的工作:

public class EnumToStringConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            Type type = value.GetType();
            string name = Enum.GetName(type, value);
            if (name != null)
            {
                FieldInfo field = type.GetField(name);
                if (field != null)
                {
                    DescriptionAttribute attr =
                           Attribute.GetCustomAttribute(field,
                             typeof(DescriptionAttribute)) as DescriptionAttribute;
                    if (attr != null)
                    {
                        return attr.Description;
                    }
                }
            }
        }
        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

完成此操作后,我DataTemplate为 ListPicker 项目创建了一个,通过 a 设置 TextBlock 的 Text 属性的值Binding并使用Converter

<DataTemplate x:Key="ListPickerDataTemplate">
    <Grid>
        <TextBlock Text="{Binding Converter={StaticResource EnumToStringConverter}}"/>
    </Grid>
</DataTemplate>

我以与之前相同的方式填充 ListPicker:

PetListPicker.ItemsSource = Enum.GetValues(typeof(Pet));

现在我的 ListPicker 显示了项目的本地化值,优点是SelectecItemListPicker 的属性可以绑定到 Enum 类型的属性。

例如,如果我的 ViewModel 中有以下属性,我想在其中存储所选项目:

public Pet MyPet {get; set;};

我可以只使用绑定:

<toolkit:ListPicker x:Name="MyListPicker" SelectedItem="{Binding MyPet, Mode=TwoWay}" ItemTemplate="{StaticResource ListPickerDataTemplate}"/>
于 2013-09-04T09:07:59.873 回答
1

最简单的方法是编写一个方法来查找翻译后的字符串并将它们返回到一个数组中。(你也可以通过向枚举添加属性来做到这一点,但我个人认为这比它的价值要麻烦得多。)

我的意思是这样的:

public string[] TranslatedPetsEnum()
{
    string[] result = new []
    {
        Resources.PetCat,
        Resources.PetDog,
        Resources.PetPlatypus
    };

    return result;
}

然后,您只需执行以下操作:

PetListPicker.ItemsSource = TranslatedPetsEnum();

如果您只想翻译一个枚举值:

public string TranslatePet(Pets pet)
{
    switch (pet)
    {
        case Pets.Dog:      return Resources.PetDog;
        case Pets.Cat:      return Resources.PetCat;
        case Pets.Platypus: return Resources.PetPlatypus;
        default:            return Resources.PetUnknown;
    }
}

您还可以实现TranslatedPetsEnum()using TranslatePet()which 可能更易于维护:

public string[] TranslatedPetsEnum()
{
    Pets[] pets = (Pets[]) Enum.GetValues(typeof(Pets));
    string[] result = new string[pets.Length];

    for (int i = 0; i < pets.Length; ++i)
        result[i] = TranslatePet(pets[i]);

    return result;
}

(还有一点:正确的命名约定应该是调用 enum Pet,而不是Pets。复数枚举名称应该用于具有可以一起 ORed 的值的枚举。)

于 2013-09-03T15:24:47.267 回答
0

我在 WPF 中的首选方法是,它在 Windows Phone 中不起作用

<ComboBox SelectedValuePath="Tag" SelectedValue="{Binding Side}">
     <ComboBoxItem Tag="{x:Static local:Side.Bid}" Content="Buy"/>
     <ComboBoxItem Tag="{x:Static local:Side.Ask}" Content="Sell"/>
</ComboBox>

内容中的“购买”和“出售”独立于绑定,然后以与其他所有内容相同的方式进行本地化。与公认的答案相比,这种方法确实有不同的优点和缺点,因此它可能对某些人有益。

因为ListPicker不支持SelectedValueand SelectedValuePath,而且 Windows Phone 不支持x:Static,所以这在 Windows Phone 中无法轻松完成 - 除非您有一个 GUI 库,它ListPicker比工具包中的库更有用。如果您的更昂贵的 ListPicker 支持SelectedValuePath,请向下滚动以查看如何解决缺少x:Static.

通过跳过绑定(或通过绑定到 set/get 后面代码中的中间变量)可以完成一些类似的实现:

<toolkit:ListPicker Name="picker" SelectionChanged="OnSelectionChanged">
    <toolkit:ListPickerItem Content="Buy" Tag="{x:Static local:Side.Bid}" />
    <toolkit:ListPickerItem Content="Sell" Tag="{x:Static local:Side.Ask}" />
</toolkit:ListPicker>

void OnSelectionChanged(...)
{
    if (DataContext != null && picker.SelectedItem != null)
       (DataContext as MyClass).Side= (Side)(((ListPickerItem)picker.SelectedItem).Tag);
}

void Init()
{
    picker.SelectedItem = picker.Items.First(i => (DataContext as MyClass).Side.Equals(((ListPickerItem)i).Tag));
}

当然这行不通,因为 Windows Phone 8 不支持x:Static. 为了解决这个问题,我们需要这个小宝石:

public class StaticSideEnums
{
    public static Side Bid { get { return Side.Bid; } }
    public static Side Ask { get { return Side.Ask; } }
}

<ResourceDictionary>
    <local:StaticSideEnums x:Key="StaticSideEnums"/>
</ResourceDictionary>

<toolkit:ListPicker Name="picker" SelectionChanged="OnSelectionChanged">
    <toolkit:ListPickerItem Content="Buy" Tag="{Binding Bid, Source={StaticResource StaticSideEnums}}" />
    <toolkit:ListPickerItem Content="Sell" Tag="{Binding Ask, Source={StaticResource StaticSideEnums}}" />
</toolkit:ListPicker>
于 2014-02-13T19:18:27.393 回答