Add to Your ASP.NET MVC Toolkit: Part II

Learn what you can do with the Telerik MVC control suite

Downloads
TelerikMVCExtensions.zip

This article is the second in a two-part series that looks at the MVC control suite released by Telerik, a well-known control developer. The Telerik control suite consists of four controls: Menu, PanelBar, Grid, and TabStrip. In the first article, I looked at the Grid control and at ScriptRegistrar and StylesheetRegistar, two components Telerik created to manage style sheets and scripts. In this article, I'll cover the remaining three controls in the Telerik MVC framework: the PanelBar, Menu, and TabStrip controls, which add application functionality for MVC view developers. 

Using the PanelBar Control

The Telerik PanelBar is a form of accordion control. Accordion controls, which are great for minimizing the amount of content on a screen, group content together with af header that can expand or collapse. Telerik creates the PanelBar control in two ways: with a BindTo method and with an Items collection. Both approaches look similar, but no approach is identical. The script in Figure 1 creates the PanelBar UI. 

For both the BindTo and Items methods you're required to take control over the user interface via a builder component passed to the action method. A little more work is required to set up the interface through the Items method, but this method gives you the most control over the user interface. 

As noted, PanelBars are accordion like in nature (which you should be readily familiar with if you have used the accordion control in the Ajax Control Toolkit). But the Telerik PanelBar is more flexible; it can change the expand mode to control whether one item is expanded at a time or multiple items are opened at a given time. Figure 2 illustrates the two different modes. 

Rendering custom interfaces can also work in a hierarchical fashion. For instance, suppose you had an object and this object has children. You might want to render a list of radio buttons within the panel. You could achieve your goal by using the BindTo method. The final result, shown in Figure 3, would be that the parent represents the content in the header and the child objects make up a collection of radio buttons within the PanelBar item’s content. Note that contents are always specified by an action; the action injects its contents into the rendering stream and gives you full control over the UI.

Using the Menu Control

The Telerik framework provides an extensive menu and sitemap system that takes advantage of all that MVC has to offer. The Menu control has many features common to other controls, and it has new features that I’ll discuss in this section. Figure 4 shows a sample Menu control; note some of the new additions, such as the orientation method that controls whether the menu renders vertically or horizontally. 

The Items method is used to construct the menu's interface (BindTo is another option; we’ll look at that next). The items added to the list render as links within the list, and these links can redirect to another page (by specifying an action or a URL) or trigger a client-side click. 

An alternative override of the BindTo method uses a NavigationBindingFactory object to set up the interface for specific object types (Figure 5). When binding to a menu using this object, the items bound to the list are mapped to a specific object type (with the idea that the menu has a variety of object types that aren’t known at the time of binding). As each of the object types is bound, the specific data-bound handler determines the menu's UI and the menu’s children. This approach offers a more flexible way to bind data to your UI.

Another new feature that the Telerik API provides is a site map. The SIteMapManager class is responsible for registering site maps and using those site maps to render the menu UI. Figure 6 creates an XML site map, loaded from a sitemap file (the same type of file added to in .NET 2.0). The data from this file is loaded and stored in the ViewData collection under a specified key. The key is important because that key is used to specify the binding in the view, as we’ll see later. 

As I mentioned earlier, the site map uses the same site map setup that ASP.NET 2.0 introduced, a *.sitemap file that contains a collection of siteMapNode elements with the title, action, and controller (action and controller attributes are a deviation). Figure 6 shows the action method that loads the sitemap, followed by the definition of the site map file that contains all the menu data.

Binding the site map data is easy; because the site map uses the ViewData collection, the BindTo method uses this key to extract the site map and render the UI accordingly. Notice that the code in Figure 6 physically assigns the site map to a ViewData entry in the action method. An alternative filter attribute, the PopulateSiteMap attribute, automatically does this work for you, if you specify it; simply specify the name of the site map entry (passed to RegisterSiteMap) and the name of the ViewData key to store the sitemap in, and you’re all set. You can specify this attribute at an action method level or at a class level (which works for all action methods). 

Note that if you use PopulateSiteMap at a class level, your controller method has to ensure that the site map has already been registered from every action method call; otherwise, you’ll get an exception that the site map doesn’t exist with the specified key. Rendering the site map hierarchy specified in Figure 6 is easy; you need only the script shown in Figure 7. Note that there are two renderings, one horizontally and one vertically. 

For a production application, the question then becomes, Where is an appropriate place to put the site map registration code? The registration process normally must happen once during an application’s life because SiteMapManager is a static class that retains the values across requests. The site map may need to be registered only once, but where does it get registered?  After all, a user can come in from any point within the application. Additionally, how often does the site map change? Are the changes on-demand, or always done in a change control process (uploaded at once off hours)? You have a couple of options to consider:

  • To ensure the site map is loaded, define the site map registration in a central component that each action method will call, and add the PopulateSiteMap attribute to every controller class.
  • Create a custom controller base class that all your controllers use, and embed the code there to register the sitemap with the SiteMapManager. Place the site map manager in the ViewData collection. An appropriate place to put this might be in the OnActionExecuting protected method.
  • Create a custom action invoker that, when the action is invoked, ensures the site map and its associated ViewData entry is present. This is any efficient method, if you already have a custom ControllerActionInvoker class.

Item Binding and ItemAction

Each menu item created uses the ItemAction method to customize the menu in additional ways. You can change any attribute to the link that’s available via a new property called the LinkHtmlAttributes property (shown below), which is a collection accessible within this process only (at the time of writing); it's not accessible within the Items or BindTo methods. 

.ItemAction((item) =>

\\{

            item.LinkHtmlAttributes.Add("target", "_blank");

\\})

Any of the menu items’ settings are available here; you can add any attributes, change the text of the menu, alter the redirect action or URL, or change any other aspect of the link. If the LinkHtmlAttributes option wasn’t available for you to specify attributes at the link level, an alternative approach exists. Each Telerik control has a client-side definition that allows you to retrieve or modify the control from a client-side API. This follows the same approach that Telerik uses in the ASP.NET AJAX framework, although these event handler definitions work a little differently because of the MVC framework. You can use either the name of a client-side function or an action that returns a delegate function to hook up a JavaScript function event handler. 

Using the Load client-side event, the handler shown in Figure 8 attaches to each hyperlink within the appropriate list item, and adds the target=”_blank”. Note the Targeted class reference; at the items level, the Menu control (at the time of writing) does not allow you to modify the link HTML attributes directly. Instead, by adding an attribute using the ContentHtmlAttributes method, the content attribute is applied to the list item, which JQuery can use to target only the links you want to open a new page (in the scenario where not every link needs to open a new window). If you like, you could just as easily target all links and skip this custom CSS class selector altogether. 

Notice how ContentHtmlAttributes added to the collection are applied to the list item that houses the menu item. Although Telerik does not support many client-side events at the moment, this functionality will surely be an enhancement to watch for.

Using the TabStrip Control

Everybody should be familiar with a TabStrip control; such controls normally are available in every major developer tool suite, and the Telerik MVC framework follows suit with a tab control that utilizes what MVC has to offer. The core definition of the tab control (Figure 9) looks like all the other controls you’ve seen so far. This is one way to specify the content of a tab. Alternatively, you could use BindTo, which would use a similar approach to displaying a tab’s content. 

Figure 10 shows other alternatives for specifying content outside of the tab. Notice the variety of options available to you. The first option loads tab content dynamically using an action method that returns a partial view. It streams the data to the client using AJAX, and replaces the contents with the updated response. This is similar to JQuery’s approach to dynamically loading content, a topic we’ll discuss at the end of this article. 

The second option looks similar to the first, but it instead renders a partial view directly; the primary difference between these two approaches relies on tab content being loaded on demand in the first example. The second example, rendering the partial view, has some positives over the former approach: The partial view rendered can use the model from the main view, where any data from the model would have to be reloaded from the dynamic approach (routing values can be passed using the LoadContentFrom option). 

Note that LoadContentFrom client-side features had a bug that this version of the project fixes. Previously, a 404 error would occur after loading more than once. Telerik provided an update script included in the sample project as the fix. In a future release, this will be fixed. 

The last two options reference action methods; the action methods will actually redirect to another area of the application (the ASP.NET MVC default application uses this approach on the home page, with the Home/About tabs). This provides a more aesthetic way to organize content, but doesn’t actually function like a tab system.

Built-In Effects

The Telerik ASP.NET AJAX framework components come with a variety of effects built into most of the controls. For instance, the TabStrip control allows use of an animation that plays when switching between tabs. Currently, the effects allowed are Expand, Opacity, Slide, and Toggle, although not every control supports these (even though you can define it for that control, it might throw an exception). Each of these effects has an open/close duration, using a millisecond count specifying how long the effect takes upon open/close operations (for example, hiding a tab is considered the close duration and showing it is the open duration). Effects are specified using the Effects method (shown below); this is common among controls that use effects. Effects are rolled into each control specifically and require no additional setup on your behalf. 

.Effects((val) =>

\\{

            val.Opacity((builder) => \\{ builder.OpenDuration(200).CloseDuration(800); \\});

\\}) 

Script Content

Each Telerik MVC control has an associated script file, and each of these script files contains a JQuery plugin specific to Telerik. Rather than use the approach that Telerik did in the MS Ajax framework, the MVC framework deeply leverages JQuery to provide its client-side features. This plugin is responsible for taking the client-side content and using script to add all the complex functionality to make the control work on the client. For instance, the PanelBar control has a tPanelBar method attached to the JQuery object (as in $(“#id”).tPanelBar()) to create the control. Once called, the control begins to respond to header clicks (for opening or closing the panel bar items). This approach is similar to Microsoft Ajax’s use of the $create method. 

The key to understanding how this works is to look at the script contents within the application (because you have to copy the scripts into your application manually). Then, look at the example site in the IE 8 debugging tool or FireFox with FireBug and view how the component registration occurs (for the PanelBar control, look specifically for the tPanelBar method call and how setting various settings changes the content of that method call). 

Using jQuery

jQuery is a great framework for doing DOM traversal and manipulation. It also supports making AJAX requests to the server, and loading content dynamically from an action method. I’m assuming that you might be at least familiar with this process and how it works. There are a few other nuances to use this approach, so I will try to explain these as we go. A standard form for getting data using jQuery may look like that shown in Figure 11

The LoadContentHere element is the marker for storing the dynamic content. The inner content gets its markup replaced with the response from the jQuery call, which is a call to an action method that returns a partial view. The partial’s view server-side content gets rendered and the client-side content returns to the get call as a string. 

This content can then be injected into the page using the replaceWith method (to replace the inner DIV of the loading DIV with the newly injected content). The replaceWith method now injects our Telerik control. We’ll see this in action soon. For now, Figure 12 shows the script that replaces the inner content. 

The actual inner content within the partial view appears below. This is the inner content that gets transformed into a string, and injected inline. Below is the partial view that gets injected into the view. This occurs in two parts; the first part is the server-side form of the partial view, followed by the output rendered within the jQuery get operation. 

You can see this inner content contains everything the PanelBar control needs to render correctly. This process has one drawback: even though the inner content clearly renders a call to convert the control to a panel bar, this statement doesn’t get the job done. Instead, the call needs to occur outside of the partial view, as shown in the previous example. 

The Telerik Advantage

The Telerik framework, which uses what MVC has to offer, contains many good features for MVC applications. The PanelBar control provides a user with an accordion-like UI, and gives a developer the ultimate level of flexibility for rendering the UI. Most of the features you saw in the PanelBar you also saw in the Menu control, which provides a dynamic UI for rendering multiple levels of menu windows. This is useful for displaying hierarchical content, such as data loaded from a site map. 

The TabStrip control is another useful and common UI for breaking the view into sections. This control also offers the ability to load the content dynamically. Each of these controls adds much value to a developer’s toolkit. Adding the capability to load or reload the view with jQuery gives Telerik an even greater advantage over your typical developer's toolkit.

Hide comments

Comments

  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
Publish