DisplayAttributeはモデル内のプロパティをローカライズしません

WPFアプリケーションでMVVMパターンを使用し、私のモデルのプロパティにローカライズされたDisplayAttributeを適用します:

class MyModel
{
    [Display(
        ResourceType = typeof(Resources.Strings),
        Name = "MyPropertyName",
        Description = "MyPropertyDescription")]
    public double MyProperty { get; set; }
}

私は、モデルプロパティのローカライズされた属性プロパティを表示する必要があります。必要なリソースファイルが適切な場所に配置され、必要なカルチャーが設定されます。私はまた、DisplayAttributeのために、ビルドアクションを組み込みリソースとして、カスタムツールをPublicResXFileCodeGeneratorとして設定しました。しかし、DisplayAttributeは、Nameパラメーターにローカライズされた文字列の代わりに "MyPropertyName"を返します。

DisplayPropertyを使用するシナリオを以下に示します。モデルプロパティの属性プロパティを表示するには、次のようなヘルパークラスを持つコンバーターを使用します。

namespace MyProject.Converters
{
   //helper class
    public class MetadataParameters
    {
        public Type ModelType { get; set; }
        public string ModelProperty { get; set; }
        public Type AttributeType { get; set; }
        public string AttributeProperty { get; set; }
    }

    public class MetadataConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var mp = parameter as MetadataParameters;
            var modelPropertyInfo = mp.ModelType.GetProperty(mp.ModelProperty);
            var attribute = modelPropertyInfo
                .GetCustomAttributes(true)
                .Cast()
                .FirstOrDefault(memberInfo => memberInfo.GetType() == mp.AttributeType);
            var attributeProperty = attribute.GetType().GetProperty(mp.AttributeProperty);

            return attributeProperty.GetValue(attribute, null);
        }
    }
}

XAMLリソース:

xmlns:converters="clr-namespace:MyProject.Converters"

XAML:

xmlns:converters="clr-namespace:MyProject.Converters"
xmlns:DataAnnotations="clr-namespace:System.ComponentModel.DataAnnotations;assembly=System.ComponentModel.DataAnnotations"
xmlns:Models="clr-namespace:MyProject.Models"


        
            
                                            
            
        
    

私は自分の単純な属性を記述し、プロパティの名前の値の代わりに(DisplayAttributeのように)ローカライズされた文字列を返します。

public class LocalizedDisplayAttribute : Attribute
{
    private readonly string name;

    public virtual string Name
    {
        get
        {
            var rm = new System.Resources.ResourceManager(typeof(Resources.Strings));
            return rm.GetString(this.name);
        }
    }

    public LocalizedDisplayAttribute(string name)
        : base()
    {
        this.name = name;
    }
}


class MyModel
{
    [LocalizedDisplay("MyPropertyName")]
    public double MyProperty { get; set; }
}

なぜDisplayAttributeはそのプロパティをローカライズしませんか? MSDNでは、この属性はローカリゼーション用に設計されていると述べています。そして、私のASP.NET MVCプロジェクトのDisplayAttributeは正しく動作します。

1
nl ru de

1 答え

DisplayAttributeといくつかのメソッドを呼び出す必要がありますGetメソッドは、あなたが探しているローカライズされた文字列を与えるでしょう。ここでは、 "MyPropertyName"というDisplayAttribute.Nameプロパティの値を取得します。

DisplayAttribute.GetName()を呼び出すと、ResourceTypeプロパティで指定されたリソースクラスが検索され、Nameプロパティを使用してリソースタイプのプロパティが反映されます。

私はあなたが要求するAttributePropertyのGetXXX()メソッドを取得するという前提でコードを変更しました。

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
  var mp = parameter as MetadataParameters;
  var modelPropertyInfo = mp.ModelType.GetProperty(mp.ModelProperty);
  var attribute = modelPropertyInfo
      .GetCustomAttributes(true)
      .Cast()
      .FirstOrDefault(memberInfo => memberInfo.GetType() == mp.AttributeType);

 //We have to call the GetXXX methods on the attribute to get a localised result.
  //return ((DisplayAttribute)attribute).GetName();
  var result = attribute
    .GetType()
    .InvokeMember(
      "Get" + mp.AttributeProperty,
      BindingFlags.InvokeMethod | BindingFlags.Instance | BindingFlags.Public,
      null,
      attribute,
      new object[0]); 
  return result;
}
4
追加された
.Nameと.GetNameの違いを指摘してくれてありがとうございます。現在、ローカリゼーションが使用されています。
追加された 著者 juFo,
私はレシピを試して、それは動作します!ありがとう。呼び出されたメンバーの名前のハードコードされた文字列を、を使用してください。
追加された 著者 user808128,