This project is read-only.

Use of Templates 

All templated controls accepts 3 kind of templates:

  1. PartialViews. In this case the template has a Type of string, and one needs to pass as parameter the name of a PartialView
  2. Razor declarative helpers. In this case the template has a Type Func<HtmlHelper<T>, HelperResult>, where T is the Type of the object to be used as ViewModel for the template. One has the option of either defining a declarative Razor helper and passing its name in the template parameter, or defining the template directly in-line.
  3. Lambda expressions.  In this case the template has a Type Func<HtmlHelper<T>, string>, where T is the Type of the object to be used as ViewModel for the template.  One has the option of either defining the Lambda Expression into another variable and then passing it in the template parameter, or defining the Lambda Expression directly in-line.

Not all templated helpers have 3 different overload, one for each type of template. Often they have just one object Type parameter to accept all kinds of templates. In this case an exception is thrown if the template is not of the right Type

It is worth to point out that both the Razor declarative helper, and the Lambda expression templates accept an HtmlHelper as their only argument . This HtmlHelper is passed to the template directly by the templated control and is already istantiated with the right Type. By using the HtmlHelper we can write the template exactly in the same way we write code in a normal View, or PartialView, with the full support of Visual Studio Intellisense.

When you decide to define the templates in-line and the template parameter is of Type object, due to the lack of information on the actual Type, Visual Studio Intellisense is not available. To recover Visual Studio Intellisense you can use the methods of the Syntactic Sugar static class:

  • _S<T>.H(-----in line Razor template-----------) , where T is the Type to be used as ViewModel. It takes a Razor in-line template as a strongly typed argument, and returns it as object
  • _S<T>.L(-----in line Lambda Expression-----------) , where T is the Type to be used as ViewModel. It takes an in-line Lambda Expression template as a strongly typed argument, and returns it as object

If you need to refer to input fileds id from JavaScript code within templates please see the PrefixedId helper.

Razor declarative helper templates

Suppose we would like to use a Razor declarative helper template as argument of the SortableListFor helper. We can define the helper this way:

 

@helper SubTasksToSort(HtmlHelper<SubTasksView> Html)
                    {
                        <div id='@Html.PrefixedId("InnerContainer")'>
                            @Html.TypedTextBoxFor(m => m.Name, new Dictionary<string, object> { { "class", "ToDoDetailName" } }, watermarkCss: "watermark")
                            @Html.ValidationMessageFor(m => m.Name, "*")

                            @Html.TypedTextBoxFor(m => m.WorkingDays, new Dictionary<string, object> { { "class", "ToDoDetailDuration" } }, watermarkCss: "watermark")
                            @Html.ValidationMessageFor(m => m.WorkingDays, "*")

                            @Html.SortableListDeleteButton("Delete", ManipulationButtonStyle.Link)
                        </div>
                    }

 

 

 and then we can pass the name of the Razor helper to the SortableListFor helper:

 

@Html.SortableListFor(m => m.SubTasks, 
                                SubTasksToSort, 
                                "SubTasksToSortAddItem", 0.7f,
                                htmlAttributesContainer: new Dictionary<string, object> { { "class", "SortableList" } },
                                enableMultipleInsert: true)

 

 

However we can also pass the Razor Helper directly in-line(the code is in the view ToDoSubTasks.cshtml of the file RazorThemedGrid):

 

@Html.SortableListFor(m => m.SubTasks, 
                                _S.H<SubTasksView>(                               
                          @<div id='@item.PrefixedId("InnerContainer")'>
                            @item.TypedTextBoxFor(m => m.Name, new Dictionary<string, object> { { "class", "ToDoDetailName" } }, watermarkCss: "watermark")
                            @item.ValidationMessageFor(m => m.Name, "*")

                            @item.TypedTextBoxFor(m => m.WorkingDays, new Dictionary<string, object> { { "class", "ToDoDetailDuration" } }, watermarkCss: "watermark")
                            @item.ValidationMessageFor(m => m.WorkingDays, "*")

                            @item.SortableListDeleteButton("Delete", ManipulationButtonStyle.Link)
                        </div>
                                
                                ), 
                                "SubTasksToSortAddItem", 0.7f,
                                htmlAttributesContainer: new Dictionary<string, object> { { "class", "SortableList" } },
                                enableMultipleInsert: true)

 

 

Please notice the use of the Syntactic Sugar class  _S.H<SubTasksView>(......to enable Visual Studio Intellisense for the in-line template.

Notice also how the item standard argument of the in-line Razor helpers has been istantiated with an HtmlHelper that enables the use of all available helpers in the template.

Lambda Expression Templates.

Lambda Expression templates can be used to write "small", templates or when we are in an aspx View (Mvc 2) and we cannot use Razor declarative helper templates. 

Suppose again we want to write a template for the SortableListFor helper. We can define a Lambda expression, this way:

 

@{
         Func<HtmlHelper<string>, string> keywordsTemplate = 
                         (x) => x.TypedTextBoxFor(m => m, watermarkCss:"watermark", overrideWatermark: "insert keyword").ToString()+
                                x.SortableListDeleteButton("Delete",  ManipulationButtonStyle.Link).ToString();
                      }

 

 

Then we can pass the keywordsTemplate variable to the SortableListFor template:

 

@Html.SortableListFor(convertedKeywords, keywordsTemplate, "KeywordInsert", 0.8f,
     htmlAttributesContainer: new Dictionary<string, object> { { "class", "SortableList" } }, itemCss: "normalRow", altItemCss: "alternateRow")
                  

 

 

However,  we can also define the Lambda Expression in-line with the help of the Syntactic Sugar class:

 

@Html.SortableListFor(convertedKeywords, 
 _S.L<string>(
   (x) => x.TypedTextBoxFor(m => m, watermarkCss:"watermark", overrideWatermark: "insert keyword").ToString()+
          x.SortableListDeleteButton("Delete",  ManipulationButtonStyle.Link).ToString()
                    ), 
            "KeywordInsert", 0.8f,
            htmlAttributesContainer: new Dictionary<string, object> { { "class", "SortableList" } }, 
                    itemCss: "normalRow", altItemCss: "alternateRow")
                  

 

Also in this case we wan use the HtmlHelper passed as argument to the Lambda Expression to access all available helpers. However, with the Lambda Expressions we cannot mix Html and C# code as in the case of Razor declarative helpers, but we are limited just to C# code. 

Invoking a Template

In exactly the same way you may invoke a Partial View with the Partial helper, you can invoke a generic template by using the TemplateFor helper:

 

public static MvcHtmlString TemplateFor<VM, T>(
            this HtmlHelper<VM> htmlHelper,
            Expression<Func<VM, T>> expression,
            object template, 
            Type subClass=null)

 

The third optional argument is needed just in the case the type used in the template is a subclass S of the Type T of the lambda expression. It just asks the TemplateFor helper to interpret the object of type T returned by expression as an instance of S.

Last edited Jun 22, 2014 at 11:39 AM by frankabbruzzese, version 12

Comments

No comments yet.