use*_*128 1 c# wpf attributes localization mvvm
我在 WPF 应用程序中使用 MVVM 模式,并将具有本地化功能的 DisplayAttribute 应用到模型的属性:
class MyModel
{
[Display(
ResourceType = typeof(Resources.Strings),
Name = "MyPropertyName",
Description = "MyPropertyDescription")]
public double MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想显示模型属性的本地化属性。必要的资源文件位于适当的位置,必要的区域性已设置。我还将“构建操作”设置为“嵌入资源”,并将“自定义工具”设置为“PublicResXFileCodeGenerator”——根据 DisplayAttribute 的要求。但 DisplayAttribute 返回“MyPropertyName”,而不是其 Name 参数的本地化字符串。
下面介绍了我使用 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<Attribute>()
.FirstOrDefault(memberInfo => memberInfo.GetType() == mp.AttributeType);
var attributeProperty = attribute.GetType().GetProperty(mp.AttributeProperty);
return attributeProperty.GetValue(attribute, null);
}
}
}
Run Code Online (Sandbox Code Playgroud)
XAML 资源:
xmlns:converters="clr-namespace:MyProject.Converters"
<converters:MetadataConverter x:Key="metadataConverter" />
Run Code Online (Sandbox Code Playgroud)
XAML:
xmlns:converters="clr-namespace:MyProject.Converters"
xmlns:DataAnnotations="clr-namespace:System.ComponentModel.DataAnnotations;assembly=System.ComponentModel.DataAnnotations"
xmlns:Models="clr-namespace:MyProject.Models"
<TextBlock
<TextBlock.Text>
<Binding
Mode="OneWay"
Converter="{StaticResource metadataConverter}">
<Binding.ConverterParameter>
<converters:MetadataParameters
ModelType="{x:Type Models:Model}"
ModelProperty="ModelProperty"
AttributeType="{x:Type DataAnnotations:DisplayAttribute}"
AttributeProperty="Name" />
</Binding.ConverterParameter>
</Binding>
</TextBlock.Text>
</TextBlock>
Run Code Online (Sandbox Code Playgroud)
我编写了自己的简单属性,它返回本地化字符串,而不仅仅是属性名称的值(如 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; }
}
Run Code Online (Sandbox Code Playgroud)
那么为什么 DisplayAttribute 不本地化它的属性呢?MSDN 表示该属性是为本地化而设计的。在我的 ASP.NET MVC 项目中 DisplayAttribute 工作正常。
DisplayAttribute 上有 Get 方法以及您需要调用的其他一些方法,这将为您提供您正在查找的本地化字符串。您在这里所做的是获取 DisplayAttribute.Name 属性的值,即“MyPropertyName”。
如果调用 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<Attribute>()
.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;
}
Run Code Online (Sandbox Code Playgroud)