Navigation Data Markup

There are currently two approaches to setting Control properties from StateContext Data:
  1. Programmatically in the codebehind
  2. Data binding to a NavigationDataSource
However, the former approach should be avoided because codebehinds should be as lean as possible and the latter can be cumbersome if only one way data binding is required.

In VS 2012 Control properties can be set from StateContext Data in markup using the syntax {NavigationData key}. For example, to set a Literal's Text property to the StateContext item with key 'name' see below.

<asp:Literal ID="Literal1" runat="server" Text="{NavigationData name}" />
Before using this feature the NavigationControlBuilderInterceptor must be registered in the Web.config as shown below.

<compilation debug="true" targetFramework="4.5" controlBuilderInterceptorType="Navigation.NavigationDataControlBuilderInterceptor, Navigation">
	<!-- other config elided -->
</compilation>
The StateContext Data item does not have to be a string, any convertible Type is valid. Format strings are also supported using the syntax {NavigationData key,format}. For example, if the 'date' key maps to a DateTime in StateContext then to use its short date representation see below.

<asp:Literal ID="Literal1" runat="server" Text="{NavigationData date,{0:d}}" />
The syntax is not limited to string Control properties. For example, if there's a bool object in StateContext Data with key 'show' then it can be used to determine a Control's visibility (see below).

<asp:Button ID="Button1" runat="server" Visible="{NavigationData show}" />
Setting a bool Control property from the negation of a StateContext Data item is supported using the syntax {NavigationData !key}. For example, for a bool stored in StateContext Data with key 'hide' its negation can be used as shown below.

<asp:Button ID="Button1" runat="server" Visible="{NavigationData !hide}" />
This NavigationData markup syntax can also be used against Control events. However, this requires the StateContext Data item to be a bool because when the associated event fires this item is toggled, i.e., if false it will be set to true and vice versa (see below for example usage).

<asp:Button ID="Button1" runat="server" OnClick="{NavigationData show}" />

Sample Web Site

A common requirement, unsupported by the Pager Control, is display the total count of rows. This value is already stored in StateContext Data as totalRowCount, because it's needed by the Pager to determine whether there's a next page, so the NavigationData markup syntax can be used to display it on the page by adding a new Literal Control after the Pager as show below.

<asp:Literal ID="Literal1" runat="server" Text="{NavigationData totalRowCount}" />
To make this number meaningful a bit of descriptive text is necessary, so the string formatting capabilities of the syntax can be used to provide this context as shown below.

<asp:Literal ID="Literal1" runat="server" Text="{NavigationData totalRowCount,Total Count {0}}" />
Rather than show both the name and date filters when the page first loads, it makes sense to show just the name filter and hide the lesser-used date of birth filter away, with a button provided to access it if required. To this end the date of birth Label and TextBox will be wrapped in a PlaceHolder with its Visible property set using the NavigationData markup syntax as show below*.

<asp:PlaceHolder runat="server" Visible="{NavigationData dateFilterVisible}" >
	<asp:Label ID="Label2" runat="server" Text="Min Date of Birth" AssociatedControlID="TextBox2" />
	<asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("[minDateOfBirth]") %>' />
</asp:PlaceHolder>
Pressing F5 will throw an exception becaue the dateFilterVisible StateContext Data item is null. It needs to be initialised to false. For now this can be done in the Page_Load method as shown below, but this will be removed in the ASP.NET Routing section when an easier method of setting default values is discussed.

protected void Page_Load(object sender, EventArgs e)
{
	if (!IsPostBack)
		StateContext.Data["dateFilterVisible"] = false;
}
This time pressing F5 is successful but the date of birth filter is always invisible. To address this a Button can be added with its OnClick event set using NavigationData markup syntax as shown below.

<asp:Button ID="Button2" runat="server" Text="Show Date of Birth Filter" OnClick="{NavigationData dateFilterVisible}" />
Clicking the Button causes the dateFilterVisible StateContext Data item to be set to true which in turn sets the PlaceHolder to be visible. Finally, to hide the Button after it's been clicked the NavigationData negation markup syntax can be used against its Visible property as shown below.

<asp:Button ID="Button2" runat="server" Text="Show Date of Birth Filter" Visible="{NavigationData !dateFilterVisible}" OnClick="{NavigationData dateFilterVisible}" />

*The validation warning flagged against the Visible property's NavigationData markup can be ignored

Last edited Dec 21, 2012 at 8:47 PM by GrahamMendick, version 2