views:

88

answers:

3

As well as DisplayName eg.

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

Html.LabelFor(model => model.Address1) 

I have a requirement to show tooltips eg.

[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) 

Can I extend the DisplayName DataAnnotation to do this? I can't see how it can be done.

Thanks!

+1  A: 

You'd have to provide your own extension method for Html.LabelFor() (and the like for that matter) that would take into consideration tool tip attribute. It doesn't necessarily have to be derived from data annotations, since it's going to be custom handled.

You could of course inherit from DisplayName and then use that one. What you'd get doing this? You'd only have to provide a single attribute like DisplayNameWithTooltip that would then work as DisplayName and you'll use it in our code to get tooltip as well.

Additional edit

If your tooltips should be implemented by using HTML element's title attribute, then I didn't mean to use some special string syntax in DisplayName attribute but rather create a new attribute class that inherit DisplayNameAttribute:

public class DisplayNameWithTooltipAttribute: DisplayNameAttribute
{
    public string Tooltip { get; private set; }

    public DisplayNameWithTooltipAttribute(string displayName, string tooltip) : base(displayName)
    {
        this.Tooltip = tooltip;
    }

    ...
}

And then use your custom attribute:

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

This way you won't have to parse your strings and other code will be able to use it as well since it inherits from DisplayName (because code probably uses calls IsAssignableFrom calls and similar).

Robert Koritnik
I think I can see what your getting at, I could potentially do this [DisplayName("Address line 1 | The first line of your address as it appears on you bank statement")] extend Html.LabelFor() and split at the " | " to get the two values. But that seems like a nasty hack to me. Is what you mean? To clarify the tooltip may not be shown directly next to the label.
longhairedsi
+1  A: 

This should get you in the right direction. It's an extension method that grabs the model property you're passing in. (if you're using MVC3 you can replace MvcHtmlString.Create with 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("");

}
BuildStarted
+1  A: 

This is how I would do it. Time for some Champions League, I can clarify the code tomorrow if you want.

First a attribute:

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

    }

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

    }
}

And then a html helper to allow us to write 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("");
    }
}

Usage would then be this:

Your model:

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

And in your view:

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