質問

I am having trouble finding any decent documentation on how HTML helpers render the HTML elements. For example, with Html.TextBoxFor, how can I specify the CSS class or id for the element? Is there any good documentation on HTML helpers? I can only find a few very specific examples on the web, and I find the MSDN documentation rather confusing...

役に立ちましたか?

解決

I'm assuming your confusion with the docs extends from all the generic typing and talk of expressions. Looking a method definitions when you're not overly familiar with those concepts can be overwhelming. Let's take a look at the overload for TextBoxFor that accepts htmlAttributes:

public static MvcHtmlString TextBoxFor<TModel, TProperty>(
    this HtmlHelper<TModel> htmlHelper,
    Expression<Func<TModel, TProperty>> expression,
    Object htmlAttributes
)

The <Type> bits are generics, which allows types that can't be known at compile time to still be used within a method or class. Generics are pretty high-level, and I can't really give a good explanation here, but simply, it's like a creating a contract. The method above tells the compiler essentially, "Hey, I'm going to be working with two types I don't know yet, but I'm going to call them TModel and TProperty. So, wherever you see those, just replace them with the right types once they're known." This give the helper the very necessary ability to be type-agnostic. Otherwise, you'd have to have a separate helper for each unique type being used, and since it's most often dealing with user-defined types, that would be an impossible feat. For the purposes of how to use the method, you can just ignore these.

As for the parameters, the docs give the following description:

Type Parameters

TModel
         The type of the model.

TProperty
         The type of the value.

Parameters

htmlHelper
         Type: System.Web.Mvc.HtmlHelper
         The HTML helper instance that this method extends.

expression
         Type: System.Linq.Expressions.Expression>
         An expression that identifies the object that contains the properties to render.

htmlAttributes
         Type: System.Object
         An object that contains the HTML attributes to set for the element.

The "type parameters" are the generics we talked about before. Though it's not true always with generics, in this case, at least, the type parameters are passed automatically, so you don't need to be concerned with that.

The first actual parameter, htmlHelper, is a silent parameter. HTML helpers, along with all the other helpers in Razor, are implemented as extensions. An extension simply means that you're taking some existing type and adding new methods to it. You do this by implementing a static class and then adding static methods to that class the take as their first parameter the type you want to extend prefixed with this. For example, to extend String, I would add:

public static class MyStringExtensions
{
    public static string AwesomeExtensionMethod(this string s)
    {
        // do something with str
    }
}

That then allows me to do someString.AwesomeExtensionMethod(), and someString is then passed into the first parameter for the method to work with. The same thing is going on with the HTML helpers.

The second parameter, is an expression. Understanding these are tied up in understanding other high level concepts like lambdas and delegates. I won't go into a full explanation here, as there's plenty of info about these topics available online if you're interested. Simply, this parameter is the m => m.SomeModelProperty jazz you always see, and lets the helper know what model property it's supposed to work on.

The final parameter is just an object. It will simply take whatever it's passed and attempt to pull out a dictionary of key value pairs that apply to attributes on the HTML element it's going to generate. Now, that doesn't mean you can really pass anything, some things would just not work, but what it does allow you to do by accepting object is allow you pass an anonymous object, which means you don't have to bother creating some custom class or instance of a class just to pass the attributes. Anonymous objects take the form:

new { [Some Key] = [Some Value] }

The helper then takes this anonymous object and creates a RouteValueDictionary from it. That seems a little weird, admittedly, but Microsoft implemented this functionality in part to enable the routing system of MVC, and they simply got lazy with the helpers and used the same methodology of the routing system.

Anyways, all that is to say that all you need to do is specify the attributes you wanted added/modified in your anonymous object, and the helper will make the adjustments, for example:

@Html.TextBoxFor(m => m.Foo, new { id = "Bar" })

There's two caveats, though. 1) Certain reserved keywords like "class" are not allowed. So in order to specify an attribute name that also happens to be a reserved keyword, you prefix it with @:

@Html.TextBoxFor(m => m.Foo, new { @class = "foo" })

2) Hyphens are not allowed, so if you need to specify something like a data-* property, you need to use underscores in place of the dashes:

@Html.TextBoxFor(m => m.Foo, new { data_bind = "value: Foo" })

The RouteValueDictionary will convert this to data-bind as it should be.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top