【问题标题】:asp.net MVC extending DataAnnotionsasp.net MVC 扩展 DataAnnotions
【发布时间】:2010-09-14 10:25:53
【问题描述】:

还有 DisplayName 例如。

[DisplayName("Address line 1 ")]
public string Address1{get; set;}

Html.LabelFor(model => model.Address1) 

我需要显示工具提示,例如。

[DisplayName("Address line 1 ")]
[ToolTip("The first line of your address as it appears on you bank statement")]
public string Address1{get; set;}

Html.LabelFor(model => model.Address1) 
Html.ToolTipFor(model => model.Address1) 

我可以扩展 DisplayName DataAnnotation 来执行此操作吗?我看不出它是怎么做到的。

谢谢!

【问题讨论】:

  • 为了澄清,工具提示可能不会直接显示在标签旁边。

标签: asp.net-mvc data-annotations


【解决方案1】:

我会这样做。是时候参加一些冠军联赛了,如果你愿意,我明天可以澄清代码。

首先是一个属性:

public class TooltipAttribute : DescriptionAttribute
{
    public TooltipAttribute()
        : base("")
    {

    }

    public TooltipAttribute(string description)
        : base(description)
    {

    }
}

然后是一个 html helper 让我们编写 Html.TooltipFor():

public static class HtmlHelpers
{
    public static MvcHtmlString ToolTipFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var exp = (MemberExpression)expression.Body;
        foreach (Attribute attribute in exp.Expression.Type.GetProperty(ex.Member.Name).GetCustomAttributes(false))
        {
            if (typeof(TooltipAttribute) == attribute.GetType())
            {
                return MvcHtmlString.Create(((TooltipAttribute)attribute).Description);
            }
        }
        return MvcHtmlString.Create("");
    }
}

用法如下:

你的模型:

public class User
{
    [Tooltip("This is the attribute for FirstName")]
    public string FirstName { get; set; }
}

在你看来:

<%= Html.ToolTipFor(x => x.FirstName) %>

【讨论】:

  • 我们可以将这个工具提示文本输入到 html 属性中,例如 @Html.TextBoxFor(model => model.FirstName, new { title = Model.FirstName.Tooltip}) 吗?请更正我的语法。
【解决方案2】:

这应该会让你朝着正确的方向前进。它是一种扩展方法,可以获取您传入的模型属性。(如果您使用的是 MVC3,您可以将 MvcHtmlString.Create 替换为 new HtmlString()

Html.ToolTipFor(m => m.Address1)

public static IHtmlString ToolTipFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) {
    MemberExpression ex = (MemberExpression)expression.Body;
    foreach(Attribute attribute in ex.Expression.Type.GetProperty(ex.Member.Name).GetCustomAttributes(true)) {
        if (typeof(TooltipAttribute) == attribute.GetType()) {
            return MvcHtmlString.Create(((TooltipAttribute)attribute).YourTooltipProperty);
        }
    }
    return MvcHtmlString.Create("");

}

【讨论】:

    【解决方案3】:

    您必须为Html.LabelFor()(以及类似的)提供您自己的扩展方法,该方法会考虑到工具提示属性。它不一定必须从数据注释中派生,因为它将被自定义处理。

    您当然可以从DisplayName 继承,然后使用那个。你这样做会得到什么?您只需要提供一个像DisplayNameWithTooltip 这样的属性,然后它就可以作为DisplayName 工作,您也可以在我们的代码中使用它来获取工具提示。

    其他编辑

    如果您的工具提示应该使用 HTML 元素的 title 属性来实现,那么我并不是要在 DisplayName 属性中使用一些特殊的字符串语法,而是要创建一个继承 DisplayNameAttribute 的新属性类:

    public class DisplayNameWithTooltipAttribute: DisplayNameAttribute
    {
        public string Tooltip { get; private set; }
    
        public DisplayNameWithTooltipAttribute(string displayName, string tooltip) : base(displayName)
        {
            this.Tooltip = tooltip;
        }
    
        ...
    }
    

    然后使用你的自定义属性:

    [DisplayNameWithTooltip("Some display name", "Some tooltip")]
    public ActionResult SetSomething(SomeObj val) { ... }
    

    这样您就不必解析字符串,其他代码也可以使用它,因为它继承自 DisplayName(因为代码可能使用调用 IsAssignableFrom 和类似的调用)。

    【讨论】:

    • 我想我可以看到你的意思,我可能会这样做 [DisplayName("Address line 1 | The first line of your address as it appears on your bank statement")] 扩展 Html. LabelFor() 并在“|”处拆分以获取两个值。但这对我来说似乎是一个讨厌的黑客攻击。是你的意思吗?为了澄清,工具提示可能不会直接显示在标签旁边。
    【解决方案4】:

    如果您使用的是元数据类,在我的例子中,由于 DB-first 模型,Alexn 助手不会返回 Tooltip 属性的值,下面的助手会。

    public static MvcHtmlString ToolTipFor<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression)
    {
        var expressionBody = (MemberExpression)expression.Body;
        Type type = expressionBody.Expression.Type;
    
        MetadataTypeAttribute[] metadataAttributes = (MetadataTypeAttribute[])type.GetCustomAttributes(typeof(MetadataTypeAttribute), true);
        foreach (MetadataTypeAttribute metadataAttribute in metadataAttributes)
        {
            var metadataPropertyAttributes = metadataAttribute.MetadataClassType.GetProperty(expressionBody.Member.Name).GetCustomAttributes(false);
            foreach (Attribute metadataPropertyAttribute in metadataPropertyAttributes)
            {
                if (typeof(TooltipAttribute) == metadataPropertyAttribute.GetType())
                {
                    return MvcHtmlString.Create(((TooltipAttribute)metadataPropertyAttribute).Description);
                }
            }
        }
        return MvcHtmlString.Create("");
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多