For those of you who have been sitting on the sideline waiting for “Orcas” to ship before you take a look at the new features in ASP.NET 3.5, it’s time for you to get in the game.

Microsoft released Visual Studio 2008 and .NET 3.5 in November 2007. I have good news and, depending on your perspective, I have either bad news or good news. If you were hoping ASP.NET 3.5 would be released with a variety of new controls, features, and architectural changes then I have bad news for you. If you’re still trying to master all the controls, features, best practices, project structures, deployment options, and architectural changes introduced when ASP.NET went from version 1.1 to 2.0, I have good news for you. Don’t get me wrong, there are plenty of new things you will want to take advantage of in ASP.NET 3.5, but the changes from ASP.NET 2.0 to ASP.NET 3.5 are more additive and incremental than monumental.

I’ll describe the changes in ASP.NET 3.5 as one of two categories: ASP.NET 3.5 specific features (new controls, for example) and ASP.NET-related Visual Studio 2008 enhancements such as nested master page support.

The DataPager only works with the new ListView control since the ListView control is the only control that implements the IPageableItemContainer interface.

In this article I’ll review these new ASP.NET 3.5 specific features:

  • The ListView control
  • The DataPager control
  • The LinqDataSource
  • Integrated AJAX support
  • Improved designer support for AJAX control extenders

Likewise, in this article I’ll review these new ASP.NET 3.5-related Visual Studio 2008 enhancements:

  • Nested Master Page support
  • Multi-Framework Targeting
  • Enhanced Web design experience
  • JavaScript IntelliSense
  • JavaScript debugging
  • CSS Properties window
  • Manage Styles tool window

Before I get into the details on what’s new in ASP.NET 3.5, I want to touch on the subject of compatibility between Visual Studio 2005 (.NET 2.0) and Visual Studio 2008 (.NET 3.5). Microsoft paid particular attention to making sure that .NET 3.5 is a smooth upgrade from .NET 2.0 with a goal of not requiring you to modify any existing code when moving your code to .NET 3.5.

Another piece of good news is that there are not any project model changes with Visual Studio 2008. When building new ASP.NET applications you can choose from the Web Site or Web Application project models and select the .NET Framework you want the project to target. I’m getting ahead of myself here. I’ll dig deeper into the multi-framework targeting features later in the article.

ASP.NET 3.5 Specific Features

I will start with the ASP.NET 3.5 specific features and then move on to the ASP.NET 3.5-related Visual Studio 2008 enhancements. I’ll first discuss a couple new controls added to ASP.NET 3.5, starting with the ListView and the DataPager.

The ListView Control

Imagine that you could have an ASP.NET control with the free form templating capabilities of the Repeater control and the data editing capabilities of the DataGrid control. Imagine no more because that control exists in ASP.NET 3.5-the new <asp:ListView> control.

The ListView supports data binding to all of the traditional data sources like SQLDataSource, ObjectDataSource, XMLDataSource as well as the new LinqDataSource.

You have complete control of how the ListView presents your data through the use of 11 templates.

  • LayoutTemplate
  • AlternatingItemTemplate
  • EditItemTemplate
  • EmptyDataTemplate
  • EmptyItemTemplate
  • GroupTemplate
  • GroupSeparatorTemplate
  • InsertItemTemplate
  • ItemTemplate
  • ItemSeparatorTemplate
  • SelectedItemTemplate

The two most important templates are the LayoutTemplate and the ItemTemplate. The LayoutTemplate is the outer shell containing the HTML that defines the overall look and feel of the control while the ItemTemplate contains the HTML that specifies how each bound record will appear.

The markup you use for the LayoutTemplate could be very simple or very complex. In either case, the LayoutTemplate needs to know where to place the rendered code for the ItemTemplate. You do this by adding a server-side control to the LayoutTemplate and assigning its ID to “ItemPlaceholder” and while that exact name is required, no, it is not case sensitive (Listing 1). Alternatively you can specify the name of the placeholder control by setting the ListView’s ItemPlaceHolderID property to the name of the control. Either way, the LayoutTemplate needs to know where the content rendered by the ItemTemplate (and all other templates) is supposed to go.

The ItemTemplate in Listing 1 uses labels to display the CompanyName and City for each entry in the Customer table.

Now I’ll move from a simple example to an example complete with the ability to insert, update, and delete data. I used the ListView’s smart tag option (Figure 1) to configure the data capabilities as well as the look and feel I wanted for this sample (Figure 2). The result is a ListView complete with the templates that control the formatting for adding, updating, and deleting records in the ListView (Listing 2).

Figure 1:  Select Configure ListView for ListView configuration options.
Figure 1: Select Configure ListView for ListView configuration options.
Figure 2:  ListView configuration options include selecting a layout, style, data updating options, and paging.
Figure 2: ListView configuration options include selecting a layout, style, data updating options, and paging.

What if the result set being returned from your data source is large, say over 100 records? Straight out of the box, the ListView control does not support paging, but that is not a problem because it does work hand-in-hand with the new DataPager control.

The DataPager Control

As its name states, the <asp:DataPager> control provides paging capabilities. It is an external control that points at the control it provides paging support for. As an external control, you gain the advantage of being able to place it anywhere on the page (or as many as you want on the page) and configuring what it is going to look like. The DataPager works with controls that implement the IPageableItemContainer interface. At the moment, the DataPager only works with the new ListView control since it is the only one that implements the IPageableItemContainer interface.

The AJAX Control Toolkit is a great community-driven collection of free control extenders that you can use to easily add to AJAX functionality to your pages.

In Listing 3 I have extended the basic ListView sample code by adding a DataPager. The DataPager’s PageControlID specifies which control the DataPager will provide paging support for, ListView2 in this example. The PageSize setting determines how many rows of data will be displayed on each page; five in this example. There are three different types of field controls available, NextPreviousPagerField, NumericPagerField, and TemplatePagerField. This sample in Listing 3 uses NextPreviousPagerField and NumericPagerField (Figure 3).

Figure 3: A Web page utilizing the DataPager control and the NextPreviousPagerField and NumericPagerField options.
Figure 3: A Web page utilizing the DataPager control and the NextPreviousPagerField and NumericPagerField options.

The NextPreviousPagerField provides an interface for the user to move from page to page or jump to the first or last page (Figure 4). The NumericPagerField provides an interface for the user to select a page by page number (Figure 5). The TemplatePagerField provides a mechanism for you to develop a custom paging interface.

Figure 4:  Adding the NextPreviousPagerField in the Source window.
Figure 4: Adding the NextPreviousPagerField in the Source window.
Figure 5:  Adding the NumericPagerField in the Source window.
Figure 5: Adding the NumericPagerField in the Source window.

The LinqDataSource Control

The <asp:LinqDataSource> control is an ASP.NET control that, like the <asp:SqlDataSource> and <asp:ObjectDataSource> controls, is used to declaratively bind ASP.NET controls to a data source. What makes the LinqDataSource unique is that instead of binding directly to something such as a database or data access layer object, which you can still do, you bind to a LINQ-friendly data model such as a LINQ to SQL object relational model (ORM).

Integrated AJAX Support

Back in the day before Microsoft released ASP.NET 3.5, you had to download and install the Microsoft ASP.NET AJAX 1.0 framework in order to build or deploy an AJAX-enabled application. Those days are gone now since AJAX is now treated as a first-class citizen in Visual Studio and the libraries are now included in .NET 3.5. As a matter of fact, you will notice that when you build a new Web site you no longer need to specify an AJAX-ready Visual Studio project template (Figure 6).

Figure 6:  The new Web site dialog box does not contain AJAX-specific templates.
Figure 6: The new Web site dialog box does not contain AJAX-specific templates.

One of my initial concerns when installing Visual Studio 2008 was how well it, along with NET 3.5, would co-exist on my machine already containing Visual Studio 2005 and related installed extensions, such as AJAX 1.0 and .NET 3.0 for example. Fortunately, when you create a new Web Site or new ASP.NET Web Application project, the 3.5 version of the System.Web.Extensions assembly containing the AJAX libraries is automatically added as a project resource. Since System.Web.Extensions v3.5 is a super-set of System.Web.Extensions v1.0 your AJAX 1.0 code should run unchanged in v3.5.

Improved Designer Support for AJAX Control Extenders

AJAX control extenders provide a way to add capabilities and functionality to controls already on a page. The ASP.NET AJAX Control Toolkit is a great community-driven collection of free control extenders that you can use to easily add AJAX functionality to your pages. With Visual Studio 2005 you had to manually wire up the controls with the extender control you wanted to use. Visual Studio 2008’s improved designer support for ASP.NET AJAX control extenders has made the process much easier by providing Smart Tag options to add or remove extenders from a particular control (Figure 7). When Visual Studio 2008 detects that one or more extenders exist for the control you have selected it will display the control’s Smart Tag. Selecting Add Extender will display the Extender Wizard for you to select which extender you would like to use (Figure 8).

Figure 7:  When Visual Studio 2008 detects extenders are present for a control, Add Extender is added to the Smart Tag options..
Figure 7: When Visual Studio 2008 detects extenders are present for a control, Add Extender is added to the Smart Tag options..
Figure 8:  You can select an extender for a specific control type.
Figure 8: You can select an extender for a specific control type.

The Visual Studio 2008 IDE has been enhanced to improve your productivity when developing Web applications.

Nested Master Pages Support

I have personally been waiting for this one for a while now. While the concept of nested master pages isn’t new to ASP.NET 3.5, as you are probably aware, Visual Studio 2005 didn’t really support nested master pages. The problem was that pages based on master pages could not be edited within the Visual Studio 2005 designer. Microsoft has corrected this behavior with Visual Studio 2008.

The process for creating a nested master page is slightly different depending on which project model you are using: Web Site or Web Application Project. I’ll use a project based on the Web Application Project model for this example. I’ll add a new item to a project and select the Nested Master Page template and enter a name for the nested master. I selected Training.master (Figure 9). Next I need to select the master page I want to base my nested master page on. I selected a master page named TakeNote.master (Figure 10). The TakeNote.master page contains a graphic, menu structure, a single content place holder, and page footer (Figure 11). A common scenario for nested master pages is creating a master page for each department within an organization. Using the TakeNote.master as a base master page I could create nested master pages for departments such as training or consulting and customize them with text and graphics specific to that department. New pages for each department would use the department-specific nested master page. With this scenario mind I have added a heading and ContentPlaceHolder control in the Training.master (Listing 4).

Figure 9:  The Nested Master Page template has been added to the Add New Item dialog box.
Figure 9: The Nested Master Page template has been added to the Add New Item dialog box.
Figure 10:  Select the master you wish to base your nested master page on.
Figure 10: Select the master you wish to base your nested master page on.
Figure 11: A master page containing a header, menu, and footer.
Figure 11: A master page containing a header, menu, and footer.

The process for creating a new page from a nested master page is the same as it was in ASP.NET 2.0. The good news is that now you can work with the new nested master page based in the WYSIWYG Designer in Visual Studio 2008.

Multi-Framework Targeting

I never gave it much thought at the time but previous versions of Visual Studio were tied to a specific version of the .NET Framework. For example, when Visual Studio 2005 was released you created applications based on .NET 2.0. That started to change a bit when Microsoft released .NET 3.0 since you could extend Visual Studio 2005 to create .NET 2.0 and .NET 3.0 applications.

With the release of Visual Studio 2008 Microsoft has taken that idea to the next logical step. When you open an existing project, or create a new one, you are given the option to select which framework version you want to target (Figure 12). The Visual Studio 2008 IDE will adjust itself to your framework selection and only offer features, options, controls, templates, and assemblies, among other things, based on the targeted framework. This includes automatically updating the assemblies referenced in your project and sections in the Web.config file.

Figure 12:  You can target a specific framework version when creating a new Web site.
Figure 12: You can target a specific framework version when creating a new Web site.

One of the benefits of the multi-framework targeting support is that all of the new features added to Visual Studio 2008 like nested master page support, enhanced JavaScript support, and the HTML editor enhancements, are available to you as you continue to work on and support your ASP.NET 2.0-based Web sites. Yes, you read that right. You can use Visual Studio 2008 to open your ASP.NET 2.0 projects without upgrading them to the .NET 3.5 framework while taking advantage of all the new Visual Studio enhancements.

The process of specifying which version of the .NET Framework to target for an existing project depends on which project model you are using and unfortunately, which language you are using. If you are using the Web Site project model, regardless of the language selected, select the Build option on the project Property Pages and select the framework you want to target from the dropdown (Figure 13). If you are using the Web Application project model, here is where things get interesting. For projects written in C#, things are simple. Open the project properties and select the framework you wish to target on the Application tab (Figure 14). For Visual Basic projects created with the Web Application Projects model, open the project properties, select the Compile tab, and click the Advanced Compile Options button. Select the framework from the Target framework dropdown (Figure 15).

Figure13:  For existing Web site projects you can specify the target framework from the project properties.
Figure13: For existing Web site projects you can specify the target framework from the project properties.
Figure 14:  For C# Web application projects you can specify the target framework from the Application tab on the Property Pages.
Figure 14: For C# Web application projects you can specify the target framework from the Application tab on the Property Pages.
Figure 15:  For Visual Basic Web application projects you can specify the target framework on the Advanced Compiler Settings dialog box.
Figure 15: For Visual Basic Web application projects you can specify the target framework on the Advanced Compiler Settings dialog box.

Note that Visual Studio 2008 only supports targeting your application to version 2.0 and higher, so you won’t see versions 1.0 and 1.1 of the .NET Framework as options.

I encourage you to experiment with changing the target framework on a sample project and take a look at the changes Visual Studio 2008 implements automatically.

Enhanced Web Designer

Visual Studio 2008 and Expression Web now share the same visual web designer. This is a welcome change since the first time you jump from the Design pane to the Source pane and back again you will find that performance has improved and additional functionality has been added.

The Split View feature displays the Design View and the HTML source in two different panes at the same time (Figure 16). While in Split View, changes you make in the Design pane automatically updates the source in the HTML pane. You would expect that changes you make in the HTML source pane would automatically be reflected in the Design pane, right? Wrong. You need to either save the page or click the button displayed at the top of the Design pane to synchronize the two panes.

Figure 16:  The Split pane enables you to see the HTML source and Design surface at the same time.
Figure 16: The Split pane enables you to see the HTML source and Design surface at the same time.

By default the two panes are split horizontally with the HTML pane on top and the Design pane on the bottom. To display the two panes side-by-side, from the Tools menu select Options, make sure Show All Settings is checked, drill into the HTML Designer option, select General, and check the Split views vertically option (Figure 17).

Figure 17:  You can specify a vertical or horizontal display for the Split pane.
Figure 17: You can specify a vertical or horizontal display for the Split pane.

While you view the Options dialog box, let me point out a nice addition made to Visual Studio 2008. Select the Text Editor option, drill into the HTML option and select the Validation option. Right out of the box, Visual Studio 2008 is configured to display those pesky HTML, CSS, and JavaScript errors as warnings instead of errors (Figure 18).

Figure 18:  Select the option for HTML and CSS warnings to stop getting them listed as errors.
Figure 18: Select the option for HTML and CSS warnings to stop getting them listed as errors.

JavaScript IntelliSense

For years I have taken the IntelliSense capability inside Visual Studio for granted but that changed quickly the more I began writing client-side JavaScript code. If you are like me, you will really appreciate Visual Studio 2008’s built-in support for JavaScript IntelliSense. Wow, this makes such a difference writing JavaScript code in Visual Studio 2005 versus Visual Studio 2008. Being able to select JavaScript keywords and language features from an IntelliSense list makes building AJAX applications so much easier (Figure 19).

Figure 19:  IntelliSense displays JavaScript keywords and types.
Figure 19: IntelliSense displays JavaScript keywords and types.

IntelliSense also extends to external JavaScript libraries as well. I have created a CodeMagazine.js file that contains a single function. You can optionally include comments that will provide a richer IntelliSense experience when the function is referenced (Listing 5). You just need to declare an external JavaScript reference either manually or by dragging the .js file into the <HEAD> tag and IntelliSense picks up on the functions contained in the external library (Figure 20).

Figure 20:  IntelliSense picks up the members of an external JavaScript library.
Figure 20: IntelliSense picks up the members of an external JavaScript library.

JavaScript Debugging

With the increased popularity of AJAX-enabled Web applications, the improved support in Visual Studio 2008 for debugging JavaScript code will come as welcome news. If you have had to debug JavaScript code in the past, I am sure you will agree that one of the frustrating things about debugging JavaScript code with Visual Studio 2005 was that you had to run your ASP.NET application before you could set any breakpoints in the debugger. Fortunately, Microsoft dramatically improved this situation because you can now set breakpoints in your JavaScript code located in regular ASP.NET pages (.aspx), external code files (.js), and in your master pages (.master) (Figure 21).

Figure 21:  You can set breakpoints in your JavaScript code.
Figure 21: You can set breakpoints in your JavaScript code.

In addition, you can now set breakpoints in your client-side JavaScript code and your server-side Visual Basic or C# code on the same page and utilize a single debugger session to step though all of the code (Figure 22**).**

Figure 22:  The runtime debugger displaying a JavaScript breakpoint.
Figure 22: The runtime debugger displaying a JavaScript breakpoint.

Also, I think one of the most significant additions to the JavaScript debugging experience is the improved object inspection support, which provides more detailed object property and property type information (Figure 23).

Figure 23:  JavaScript object inspection has been improved.
Figure 23: JavaScript object inspection has been improved.

CSS Properties Window

The first of the new CSS features added to Visual Studio 2008 that I will cover is the CSS Properties window. You will find it about half way down the View menu. The CSS Properties window shows you all of the CSS settings currently being applied to any ASP.NET server control or HTML element (Figure 24). A red line displayed through the property name indicates that it has been overridden. Overridden style properties are not applied to the selected element. Click the Summary button to display all of the properties that are applied to the selected element (Figure 25). As you can see, the new CSS Properties window makes keeping track and changing CSS values quick and easy.

Figure 24: The CSS Properties window displays all of the CSS properties for the selected item.
Figure 24: The CSS Properties window displays all of the CSS properties for the selected item.
Figure 25: The CSS Properties Summary provides a list of properties that are applied to the selected element.
Figure 25: The CSS Properties Summary provides a list of properties that are applied to the selected element.

Manage Styles Window

The Manage Styles window is a welcome addition to Visual Studio 2008. It helps you visually manage the CSS styles used on the page you are currently working with in both Design and Source view (Figure 26). You will find it on the View menu, just after the CSS Properties menu option. When an item is circled it means that rule is currently used somewhere on the current page. Hover over a style to display the rule values for that rule. Select a rule and a sample of what it looks like appears in the Selected Style Preview section at the bottom of the Manage Styles window. Double-click on a rule to open the style sheet it is contained in. Start making changes and you will see another feature of Visual Studio 2008-full IntelliSense within your style sheets.

Figure 26:  The Manage Styles window displays all of the styles in a CSS file and indicates which elements are in use.
Figure 26: The Manage Styles window displays all of the styles in a CSS file and indicates which elements are in use.

At the top of the Manage Styles window you’ll see an option to create new styles and an option to load an additional style sheet into the Manage Styles window if your project utilizes more than a single style sheet. You can click the Options button to display a number of display options (Figure 27).

Figure 27:  The Options button provides categorizing and display options for the CSS elements.
Figure 27: The Options button provides categorizing and display options for the CSS elements.

Summary

Hopefully I have covered enough of the new features in ASP.NET 3.5 and Visual Studio 2008 to peak your interest and jumpstart your learning process. Even if you are not ready to start using the new features in ASP.NET 3.5, because of the multi-framework targeting support in Visual Studio 2008, you can take advantage of all the new Web development features like the JavaScript debugging, JavaScript IntelliSense, improved Web designer, nested master pages, and CSS features in your ASP.NET 2.0 applications.

Listing 1: Basic ListView control

&lt;asp:ListView
    ID="ListView2" 
    runat="server" 
    DataSourceID="MyDataSource"&gt;

    &lt;LayoutTemplate&gt;
        &lt;asp:PlaceHolder 
            ID="itemPlaceholder" 
            runat="server"&gt;
        &lt;/asp:PlaceHolder&gt;
    &lt;/LayoutTemplate&gt;

    &lt;ItemTemplate&gt;
       &lt;asp:Label
            ID="Company" 
            runat="server" 
            Text='&lt;%# Eval("CompanyName") %&gt;' /&gt;
       &lt;br /&gt;
       &lt;asp:Label 
            ID="CityLabel" 
            runat="server" 
            Text='&lt;%# Eval("City") %&gt;' /&gt;
       &lt;hr /&gt;
    &lt;/ItemTemplate&gt;
&lt;/asp:ListView&gt;

Listing 2: Data Manipulation ListView control

&lt;asp:ListView ID="ListView1" runat="server"
    DataKeyNames="CategoryID" 
    DataSourceID="SqlDataSource1" InsertItemPosition="LastItem"&gt;

    &lt;AlternatingItemTemplate&gt;
        &lt;tr style="background-color:#FFF8DC;"&gt;
            &lt;td&gt;
                &lt;asp:Button ID="DeleteButton" runat="server" 
                    CommandName="Delete" Text="Delete" /&gt;
                &lt;asp:Button ID="EditButton" runat="server" 
                    CommandName="Edit" Text="Edit" /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryNameLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryName") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="DescriptionLabel" runat="server" 
                    Text='&lt;%# Eval("Description") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryIDLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryID") %&gt;' /&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/AlternatingItemTemplate&gt;
    &lt;LayoutTemplate&gt;
        &lt;table runat="server"&gt;
            &lt;tr runat="server"&gt;
                &lt;td runat="server"&gt;
                    &lt;table ID="itemPlaceholderContainer" 
                        runat="server" border="1" 
                        style="background-color: #FFFFFF;
                        border-collapse: collapse;
                        border-color: #999999;
                        border-style:none;
                        border-width:1px;
                        font-family: Verdana, sans-serif;"&gt;
                        &lt;tr runat="server" 
                            style="background-color:#DCDCDC;
                            color: #000000;"&gt;
                            &lt;th runat="server"&gt;
                            &lt;/th&gt;
                            &lt;th runat="server"&gt;
                                CategoryName&lt;/th&gt;
                            &lt;th runat="server"&gt;
                                Description&lt;/th&gt;
                            &lt;th runat="server"&gt;
                                CategoryID&lt;/th&gt;
                        &lt;/tr&gt;
                        &lt;tr ID="itemPlaceholder" runat="server"&gt;
                        &lt;/tr&gt;
                    &lt;/table&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
            &lt;tr runat="server"&gt;
                &lt;td runat="server" 
                    style="text-align: center;
                    background-color: #CCCCCC;
                    font-family: Verdana, sans-serif;
                    color: #000000;"&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/LayoutTemplate&gt;
    &lt;InsertItemTemplate&gt;
        &lt;tr style=""&gt;
            &lt;td&gt;
                &lt;asp:Button ID="InsertButton" runat="server" 
                    CommandName="Insert" Text="Insert" /&gt;
                &lt;asp:Button ID="CancelButton" runat="server" 
                    CommandName="Cancel" Text="Clear" /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:TextBox ID="CategoryNameTextBox" 
                    runat="server" 
                    Text='&lt;%# Bind("CategoryName") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:TextBox ID="DescriptionTextBox" 
                    runat="server" 
                    Text='&lt;%# Bind("Description") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;&amp;nbsp;&lt;/td&gt;
        &lt;/tr&gt;
    &lt;/InsertItemTemplate&gt;
    &lt;SelectedItemTemplate&gt;
        &lt;tr style="background-color:#008A8C;
            font-weight: bold;
            color: #FFFFFF;"&gt;
            &lt;td&gt;
                &lt;asp:Button ID="DeleteButton" runat="server" 
                    CommandName="Delete" Text="Delete" /&gt;
                &lt;asp:Button ID="EditButton" runat="server" 
                    CommandName="Edit" Text="Edit" /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryNameLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryName") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="DescriptionLabel" runat="server" 
                    Text='&lt;%# Eval("Description") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryIDLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryID") %&gt;' /&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/SelectedItemTemplate&gt;
    &lt;EmptyDataTemplate&gt;
        &lt;table runat="server" 
            style="background-color: #FFFFFF;
            border-collapse: collapse;
            border-color: #999999;
            border-style:none;
            border-width:1px;"&gt;
            &lt;tr&gt;
                &lt;td&gt;No data was returned.&lt;/td&gt;
            &lt;/tr&gt;
        &lt;/table&gt;
    &lt;/EmptyDataTemplate&gt;
    &lt;EditItemTemplate&gt;
        &lt;tr style="background-color:#008A8C;color: #FFFFFF;"&gt;
            &lt;td&gt;
                &lt;asp:Button ID="UpdateButton" runat="server" 
                    CommandName="Update" Text="Update" /&gt;
                &lt;asp:Button ID="CancelButton" runat="server" 
                    CommandName="Cancel" Text="Cancel" /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:TextBox ID="CategoryNameTextBox" 
                    runat="server" 
                    Text='&lt;%# Bind("CategoryName") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:TextBox ID="DescriptionTextBox" 
                    runat="server" 
                    Text='&lt;%# Bind("Description") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryIDLabel1" 
                    runat="server" 
                    Text='&lt;%# Eval("CategoryID") %&gt;' /&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/EditItemTemplate&gt;
    &lt;ItemTemplate&gt;
        &lt;tr style="background-color:#DCDCDC;color: #000000;"&gt;
            &lt;td&gt;
                &lt;asp:Button ID="DeleteButton" runat="server" 
                    CommandName="Delete" Text="Delete" /&gt;
                &lt;asp:Button ID="EditButton" runat="server" 
                    CommandName="Edit" Text="Edit" /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryNameLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryName") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="DescriptionLabel" runat="server" 
                    Text='&lt;%# Eval("Description") %&gt;' /&gt;
            &lt;/td&gt;
            &lt;td&gt;
                &lt;asp:Label ID="CategoryIDLabel" runat="server" 
                    Text='&lt;%# Eval("CategoryID") %&gt;' /&gt;
            &lt;/td&gt;
        &lt;/tr&gt;
    &lt;/ItemTemplate&gt;
&lt;/asp:ListView&gt;

Listing 3: DataPager working with a ListView control

&lt;asp:ListView
    ID="ListView2" 
    runat="server" 
    DataSourceID="MyDataSource"&gt;

    &lt;LayoutTemplate&gt;
        &lt;asp:PlaceHolder 
            ID="itemPlaceholder" 
            runat="server"&gt;
        &lt;/asp:PlaceHolder&gt;
    &lt;/LayoutTemplate&gt;

    &lt;ItemTemplate&gt;
       &lt;asp:Label
            ID="Company" 
            runat="server" 
            Text='&lt;%# Eval("CompanyName") %&gt;' /&gt;
       &lt;br /&gt;
       &lt;asp:Label 
            ID="CityLabel" 
            runat="server" 
            Text='&lt;%# Eval("City") %&gt;' /&gt;
       &lt;hr /&gt;
    &lt;/ItemTemplate&gt;
&lt;/asp:ListView&gt;

&lt;asp:DataPager ID="DataPager1" runat="server" 
    PagedControlID="ListView2" 
    PageSize="5"&gt;
    &lt;Fields&gt;
        &lt;asp:NextPreviousPagerField 
            ButtonType="Button" 
            ShowFirstPageButton="True" 
            ShowLastPageButton="True" /&gt;
    &lt;/Fields&gt;
&lt;/asp:DataPager&gt;

Listing 4: Training.master markup

&lt;%@ Master Language="VB" MasterPageFile="~/TakeNote.Master" 
AutoEventWireup="false" CodeBehind="<a href="http://Training.master.vb">Training.master.vb</a>" 
Inherits="TakeNote.Training1" %&gt;
&lt;asp:Content ID="Content1"
ContentPlaceHolderID="ContentPlaceHolder"
    runat="server"&gt;
    &lt;h1&gt;Training&lt;/h1&gt;
    &lt;asp:ContentPlaceHolder ID="ContentPlaceHolder1" 
runat="server" /&gt;
&lt;/asp:Content&gt;

Listing 5: CodeMagazine.js

function AgeInDogYears(Age)
///         &lt;        summary        &gt;        This returns a person's age in dog years        &lt;/        summary        &gt;
///         &lt;        param name="Age"        &gt;        Person's Age        &lt;/        param        &gt;
///         &lt;        returns        &gt;        integer        &lt;/        returns        &gt;
{
    var DogYears = Age * 7
    return DogYears
}