来自参考资料的 DisplayName 属性? ?

我有一个本地化的应用程序,我想知道是否有可能从资源为某个模型属性设置 DisplayName

我想这样做:

public class MyModel {
[Required]
[DisplayName(Resources.Resources.labelForName)]
public string name{ get; set; }
}

但是我做不到,正如编译器所说: “属性参数必须是属性参数类型的常量表达式、 typeof 表达式或数组创建表达式”: (

是否有任何变通方法? 我手动输出标签,但我需要这些验证器输出!

132896 次浏览

如何编写一个自定义属性:

public class LocalizedDisplayNameAttribute: DisplayNameAttribute
{
public LocalizedDisplayNameAttribute(string resourceId)
: base(GetMessageFromResource(resourceId))
{ }


private static string GetMessageFromResource(string resourceId)
{
// TODO: Return the string from the resource file
}
}

可以像这样使用:

public class MyModel
{
[Required]
[LocalizedDisplayName("labelForName")]
public string Name { get; set; }
}

更新:

我知道已经太迟了,但我想补充一点:

我使用的是由 菲尔 · 哈克德提供的 传统模型元数据提供程序它更强大,更容易应用看看它: 常规模型元数据提供程序


老答案

在这里,如果你想支持多种类型的资源:

public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
private readonly PropertyInfo nameProperty;


public LocalizedDisplayNameAttribute(string displayNameKey, Type resourceType = null)
: base(displayNameKey)
{
if (resourceType != null)
{
nameProperty = resourceType.GetProperty(base.DisplayName,
BindingFlags.Static | BindingFlags.Public);
}
}


public override string DisplayName
{
get
{
if (nameProperty == null)
{
return base.DisplayName;
}
return (string)nameProperty.GetValue(nameProperty.DeclaringType, null);
}
}
}

然后像这样使用它:

    [LocalizedDisplayName("Password", typeof(Res.Model.Shared.ModelProperties))]
public string Password { get; set; }

有关完整的本地化教程,请参见 这一页

如果你使用 MVC 3和。NET 4中,可以在 System.ComponentModel.DataAnnotations命名空间中使用新的 Display属性。这个属性取代了 DisplayName属性,并提供了更多的功能,包括本地化支持。

在你的情况下,你可以这样使用它:

public class MyModel
{
[Required]
[Display(Name = "labelForName", ResourceType = typeof(Resources.Resources))]
public string name{ get; set; }
}

另外,这个属性不适用于 App_GlobalResourcesApp_LocalResources中的资源。这与这些资源使用的自定义工具(GlobalResourceProxyGenerator)有关。相反,请确保您的资源文件设置为“嵌入式资源”,并使用“ ResXFileCodeGenerator”自定义工具。

(作为进一步的侧面说明,您不应该使用 App_GlobalResourcesApp_LocalResources与 MVC。你可以阅读更多关于为什么是这种情况 给你)

通过选择资源属性并将“ Custom Tool”切换到“ PublicResXFileCodeGenerator”并将操作构建为“嵌入式资源”,我在 App _ GlobalResources 中得到了 Gunders 的回答。 请观察冈德斯在下面的评论。

enter image description here

非常有效:)

如果打开资源文件并将访问修饰符更改为 public 或 Internal,它将从资源文件中生成一个类,该类允许您创建强类型资源引用。

Option for resource file code generation

这意味着您可以改用这种方法(使用 C # 6.0)。 然后你就不用记得名字是小写还是骆驼。并且可以查看其他属性是否使用相同的资源值来查找所有引用。

[Display(Name = nameof(PropertyNames.FirstName), ResourceType = typeof(PropertyNames))]
public string FirstName { get; set; }
public class Person
{
// Before C# 6.0
[Display(Name = "Age", ResourceType = typeof(Testi18n.Resource))]
public string Age { get; set; }


// After C# 6.0
// [Display(Name = nameof(Resource.Age), ResourceType = typeof(Resource))]
}
  1. 定义属性的 资源类型,以便查找资源
  2. 定义用于资源键的属性 姓名,在 C # 6.0之后,可以使用 nameof实现强类型支持,而不必对键进行硬编码。

  3. 在控制器中设置当前线程的区域性。

Resource.Culture = CultureInfo.GetCultureInfo("zh-CN");

  1. 将资源的可访问性设置为 public

  2. 像这样在 Cshtml中显示标签

@Html.DisplayNameFor(model => model.Age)