使用Binding和不同语言进行枚举本地化

时间:2013-06-13 01:57:53

标签: c# wpf xaml localization enums

我尝试使用Binding找到从资源输出本地化枚举的解决方案。

现在我按照这样的常用方式绑定枚举:

<Page.Resources>
    <ObjectDataProvider x:Key="RootConverterType" MethodName="GetValues" ObjectType="{x:Type sys:Enum}" >
        <ObjectDataProvider.MethodParameters>
            <x:Type TypeName="settingsManager:RootConverterType"/>
        </ObjectDataProvider.MethodParameters>
    </ObjectDataProvider>

<ComboBox ItemsSource="{Binding Source={StaticResource RootConverterType}}" SelectedValue="{Binding Path=CameraPosition.Config.UI.ValueConverterType.W, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"

这不是本地化的枚举,但我希望使用本地化(使用资源中的不同语言),以及在没有ComboBox事件和显式转换的情况下从本地化字符串转换为枚举。这可能吗?如果是的话,有人可以提供简单的代码示例吗?

3 个答案:

答案 0 :(得分:1)

我认为如果你导入多个xaml文件来实现本地化是不可能的。

因为如果您将语言导入xaml,它们就是静态资源。我建议你使用绑定动态资源,并导入cs文件中的资源来初始化资源键。

Xaml像这样:

 Content="{DynamicResource UID_AppCommon_MiniPA_Close}"

CS喜欢这个:

this.Resources.MergedDictionaries.Add(your resource file);

答案 1 :(得分:1)

我正在使用包装器结构来解决这个问题:

public enum AttributeType {
  Bool, 
  Number,
  String 
}//AttributeType


public struct AttributeTypeWrapper {

    public AttributeTypeWrapper(AttributeType type) {
      this.type = type;
    }

    private AttributeType type;

    public AttributeType Type {
      get {
        return type;
      }
      set {
        type = value;
      }
    }

    public override string ToString() {
      switch(type) {
        case AttributeType.Bool:
          return Properties.Resources.txtBool;
        case AttributeType.Number:
          return Properties.Resources.txtNumber;
        case AttributeType.String:
          return Properties.Resources.txtString;
        default:
          return "Invalid AttributeType";
      }
    }
  }// AttributeTypeWrapper

请注意,它是结构而不是。因此,它是一种值类型,可以轻松设置为SelectedItemComboBox的{​​{1}}。

为了更进一步,您可以实现IValueConverte以进行简单绑定:

ListBox

然后,您可以将/// <summary> /// Convert a AttributeType into its wrapper class to display strings from resources /// in the selected language /// </summary> [ValueConversion(typeof(AttributeType), typeof(AttributeTypeWrapper))] public class AttributeTypeToWrapperConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return new AttributeTypeWrapper((AttributeType)value); } public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) { return ((AttributeTypeWrapper)value).Type; } } 直接绑定到SelectedItem类型:

enum

<AttributeTypeToWrapperConverter x:Key="convertAttrTypeToWrapper"/> <ComboBox ItemsSource="{Binding Path=DataTypes}" SelectedItem="{Binding Path=SelectedDataType, Converter={StaticResource convertAttrTypeToWrapper}}"/> 是一个DataTypes结构数组。 AttributeTypeWrapper属于类型 SelectedDataType。 (您也可以转换ItemsSource。)

这对我来说非常好。

答案 2 :(得分:0)

我找到了另一种本地化枚举的方法:

这是我的课程,您可以使用以下示例: ru_RU和en_US - 资源文件名。

public class EnumLocalizationManager:BindableObject     {         公共语言;         private CommonLocalization commonLang;         private ObservableCollection rootCoverterTypes;

    public EnumLocalizationManager()
    {
        commonLang = CommonLocalization.GetInstance;
        EnumLanguage = commonLang.Lang;
    }

    //Коллекция для локализации enum RootConverterType
    public static Dictionary<Language, ObservableCollection<string>> RootConverterLocalization = new Dictionary<Language, ObservableCollection<string>>()
    {
        {
            Language.ru_RU, new ObservableCollection<string>()
            {
                ru_RU.CameraEnumConverterTypeUndefined, ru_RU.CameraEnumConverterTypeAuto, ru_RU.CameraEnumConverterTypeNumber, ru_RU.CameraEnumConverterTypeExponent, ru_RU.CameraEnumConverterTypeDecimal, ru_RU.CameraEnumConverterTypeInteger
            }
        },
        {
            Language.en_US, new ObservableCollection<string>()
            {
                en_US.CameraEnumConverterTypeUndefined, en_US.CameraEnumConverterTypeAuto, en_US.CameraEnumConverterTypeNumber, en_US.CameraEnumConverterTypeExponent, en_US.CameraEnumConverterTypeDecimal, en_US.CameraEnumConverterTypeInteger
            }
        }
    };

    //Коллекция для локализации enum ConverterType
    public static Dictionary<Language, ObservableCollection<string>> ConverterLocalization = new Dictionary<Language, ObservableCollection<string>>()
    {
        {
            Language.ru_RU, new ObservableCollection<string>()
            {
                ru_RU.CameraEnumConverterTypeAuto, ru_RU.CameraEnumConverterTypeNumber, ru_RU.CameraEnumConverterTypeExponent, ru_RU.CameraEnumConverterTypeDecimal, ru_RU.CameraEnumConverterTypeInteger
            }
        },
        {
            Language.en_US, new ObservableCollection<string>()
            {
                en_US.CameraEnumConverterTypeAuto, en_US.CameraEnumConverterTypeNumber, en_US.CameraEnumConverterTypeExponent, en_US.CameraEnumConverterTypeDecimal, en_US.CameraEnumConverterTypeInteger
            }
        }
    };




    public ObservableCollection<string> RootConverterTypes
    {
        get { return rootCoverterTypes; }
    }

    public ObservableCollection<string> ConverterTypes
    {
        get { return coverterTypes; }
    }



    public Language EnumLanguage
    {
        get { return language; }
        set
        {
            language = value;
            ChangeEnumLanguage();

        }
    }

    private void ChangeEnumLanguage()
    {
        if (RootConverterLocalization.ContainsKey(language))
        {
            rootCoverterTypes = RootConverterLocalization[language];
        }

        if (ConverterLocalization.ContainsKey(language))
        {
            coverterTypes = ConverterLocalization[language];
        }


        RaisePropertyChanged();
        RaisePropertyChangedByName("RootConverterTypes");
        RaisePropertyChangedByName("ConverterTypes");
   }
}

}

BindableObject类是包含INotifyPropertyChanged的类。 首先 - 你的枚举必须编号(ValueConverter需要它) 对于前: public enum ConverterType     {         自动= 0,         数字= 1,         指数= 2,         十进制= 3,         整数= 4     }

public enum RootConverterType
{
    Undefined = 0,
    Auto = 1,
    Number = 2,
    Exponential = 3,
    Decimal = 4,
    Integer = 5
}

和最后一部分 - ValueConvert本身:

class EnumCameraVariantToLocalizedStringConverter:ConverterBase     {         public EnumCameraVariantToLocalizedStringConverter()         {

    }

    public override object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return (int)(CameraVariant)value;
    }

    public override object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        int index = (int)value;
        switch (index)
        {
            case 0:
                return CameraVariant.Undefined;
            case 1:
                return CameraVariant.FirstPerson;
            case 2:
                return CameraVariant.ThirdPerson;
            case 3:
                return CameraVariant.Flight;
        }
        return index;
    }
}

我使用基类的继承只是为了使用makrup扩展而不为每个转换器添加资源。

绑定本身:

<ComboBox Style="{StaticResource CameraMainSelectorStyle}"
                                            ItemsSource="{Binding Source={StaticResource EnumLocalizationManager}, Path=CameraVariant}"  
                                            SelectedIndex="{Binding Path=CameraSettingsManager.StartUpCameraModeFilter, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={valueConverters:EnumCameraVariantToLocalizedStringConverter}}"
                                            Tag="{Binding Path=CameraSettingsManager.StartUpCameraModeFilter, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
                                            SelectionChanged="StartUpCameraTypeFilter_OnSelectionChanged"/>

这是Combobox的绑定枚举。我希望事情很清楚。这里有一件事。如果您想在飞行中更改语言,则必须添加一些代码,以便在语言更改后不丢失所选项目:

if (((ComboBox)sender).SelectedIndex < 0)
            {
                if (((ComboBox) sender).Tag != null)
                {
                    CameraVariant behavior = (CameraVariant) ((ComboBox) sender).Tag;
                    ((ComboBox) sender).SelectedIndex = (int) behavior;
                }
            }

这一切。看起来有点可怕,但没有什么难的。