The second subtag represents the rela-tionship between the item nodes in the XML file and the menu items... private void PopulateMenu { DataTable menuData = GetMenuData; AddTopMenuItemsm
Trang 1LISTING 22.13 MenuXMLComplex.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<title>Menu XML Complex</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Menu
id=”Menu1”
DataSourceID=”srcMenu”
Runat=”server”>
<DataBindings>
<asp:MenuItemBinding
DataMember=”category”
TextField=”text” />
<asp:MenuItemBinding
DataMember=”item”
TextField=”text”
ValueField=”price” />
</DataBindings>
</asp:Menu>
<asp:XmlDataSource
id=”srcMenu”
DataFile=”MenuComplex.xml”
Runat=”server” />
</div>
</form>
</body>
</html>
The Menu control includes a <DataBindings> element This element includes two
MenuItemBinding subtags The first subtag represents the relationship between the
cate-gory nodes in the XML file and the menu items The second subtag represents the
rela-tionship between the item nodes in the XML file and the menu items
Trang 2Binding to Database Data
You can’t bind a Menu control directly to database data Neither the SqlDataSource nor
ObjectDataSource controls implement the IHierachicalDataSource interface Therefore,
if you want to represent database data with the Menu control, you need to perform some
more work
One option is to create your own SqlHiearachicalDataSource control You can do this
either by deriving from the base HiearchicalDataSourceControl class or implementing
the IHiearchicalDataSource interface You take this approach in the final section of this
chapter, when a custom SqlHierarchicalDataSource control is built
A second option is to build the menu items programmatically in the Menu control This is
the approach followed here
Imagine that you want to represent the contents of the following database table with a
Menu control:
CategoryId ParentId Name
This database table represents product categories The categories are nested with the help
of the ParentId column For example, the Orange Juice category is nested below the Juice
category, and the Juice category is nested below the Beverages category
The page in Listing 22.14 illustrates how you can display this database table with a Menu
control (see Figure 22.11)
Trang 3LISTING 22.14 MenuDatabase.aspx
<%@ Page Language=”C#” %>
<%@ Import Namespace=”System.Web.Configuration” %>
<%@ Import Namespace=”System.Data” %>
<%@ Import Namespace=”System.Data.SqlClient” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<script runat=”server”>
/// <summary>
/// Only populate the menu when the page first loads
/// </summary>
void Page_Load()
{
if (!Page.IsPostBack)
PopulateMenu();
}
/// <summary>
/// Get the data from the database and create the top-level
/// menu items
/// </summary>
FIGURE 22.11 Displaying database data with the Menu control
Trang 4private void PopulateMenu()
{
DataTable menuData = GetMenuData();
AddTopMenuItems(menuData);
}
/// <summary>
/// Use a DataAdapter and DataTable to grab the database data
/// </summary>
/// <returns></returns>
private DataTable GetMenuData()
{
// Get Categories table
string selectCommand = “SELECT CategoryId,ParentId,Name FROM Categories”;
string conString =
WebConfigurationManager.ConnectionStrings[“Categories”].ConnectionString;
SqlDataAdapter dad = new SqlDataAdapter(selectCommand, conString);
DataTable dtblCategories = new DataTable();
dad.Fill(dtblCategories);
return dtblCategories;
}
/// <summary>
/// Filter the data to get only the rows that have a
/// null ParentID (these are the top-level menu items)
/// </summary>
private void AddTopMenuItems(DataTable menuData)
{
DataView view = new DataView(menuData);
view.RowFilter = “ParentID IS NULL”;
foreach (DataRowView row in view)
{
MenuItem newMenuItem = new MenuItem(row[“Name”].ToString(),
row[“CategoryId”].ToString());
Menu1.Items.Add(newMenuItem);
AddChildMenuItems(menuData, newMenuItem);
}
}
/// <summary>
/// Recursively add child menu items by filtering by ParentID
/// </summary>
private void AddChildMenuItems(DataTable menuData, MenuItem parentMenuItem)
{
DataView view = new DataView(menuData);
Trang 5view.RowFilter = “ParentID=” + parentMenuItem.Value;
foreach (DataRowView row in view)
{
MenuItem newMenuItem = new MenuItem(row[“Name”].ToString(),
row[“CategoryId”].ToString());
parentMenuItem.ChildItems.Add(newMenuItem);
AddChildMenuItems(menuData, newMenuItem);
}
}
</script>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
<style type=”text/css”>
.menuItem
{
border:Solid 1px black;
width:100px;
padding:2px;
background-color:#eeeeee;
}
.menuItem a
{
color:blue;
}
.grid
{
margin-top:10px;
}
.grid td, grid th
{
padding:10px;
}
</style>
<title>Menu Database</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Menu
id=”Menu1”
Orientation=”horizontal”
StaticMenuItemStyle-CssClass=”menuItem”
Trang 6DynamicMenuItemStyle-CssClass=”menuItem”
Runat=”server” />
<asp:GridView
id=”grdProducts”
DataSourceID=”srcProducts”
CssClass=”grid”
AutoGenerateColumns=”false”
Runat=”server”>
<Columns>
<asp:BoundField
DataField=”ProductName”
HeaderText=”Product” />
<asp:BoundField
DataField=”Price”
HeaderText=”Price”
DataFormatString=”{0:c}” />
</Columns>
</asp:GridView>
<asp:SqlDataSource
id=”srcProducts”
ConnectionString=”<%$ ConnectionStrings:Categories %>”
SelectCommand=”SELECT ProductName,Price FROM Products
WHERE CategoryId=@CategoryId”
Runat=”server”>
<SelectParameters>
<asp:ControlParameter
Name=”CategoryId”
ControlID=”Menu1” />
</SelectParameters>
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
The menu items are added to the Menu control in the PopulateMenu() method This
method first grabs a DataTable that contains the contents of the Categories database table
Next, it creates a menu item for each row that does not have a parent row (each row
where the ParentId column has the value null)
The child menu items for each menu item are added recursively The ParentId column is
used to filter the contents of the Categories DataTable
Trang 7The page in Listing 22.14 also includes a GridView control that displays a list of products
that match the category selected in the menu GridView is bound to a SqlDataSource
control, which includes a ControlParameter that filters the products based on the selected
menu item
Formatting the Menu Control
The Menu control supports an abundance of properties that can be used to format the
appearance of the control Many of these properties have an effect on static menu items,
and many of these properties have an effect on dynamic menu items Static menu items
are menu items that always appear Dynamic menu items are menu items that appear only
when you hover your mouse over another menu item
First, the Menu control supports the following general properties related to formatting:
dynamic menu item is displayed after a user moves the mouse away from the menu
item
appears under each dynamic menu item
indicates that a dynamic menu item has child menu items
dynamic menu item is shifted relative to its parent menu item
menu item
for the popout image
image (By default, a triangle is displayed.)
appears above each dynamic menu item
dynamic menu item is shifted relative to its parent menu item
levels of dynamic menu items to display
value is Vertical.)
and that enables you to scroll down through menu items
Trang 8and that enables you to scroll up through menu items
link enables blind users to skip past the contents of a menu.)
appears below each static menu item
items to display
that indicates that a menu item has child menu items
menu item
the popout image
menu item is indented relative to its parent menu item
appears above each static menu item
click a menu item
This list includes several interesting properties For example, you can specify images for
scrolling up and down through a list of menu items These images appear when you
constrain the height of either the static or dynamic menu
The Menu control also exposes several Style objects You can use these Style objects as
hooks to which you can attach Cascading Style Sheet (CSS) classes:
mouse over it
over it
Trang 9Furthermore, you can apply styles to menu items based on their level in the menu For
example, you might want the font size to get progressively smaller depending on how
deeply nested a menu item is within a menu You can use three properties of the Menu
control to format menu items, depending on their level:
correspond to different menu levels
correspond to different menu levels of selected menu items
corre-spond to different menu levels of static menu items
For example, the page in Listing 22.15 illustrates how you can apply different formatting
to menu items that appear at different menu levels (see Figure 22.12)
FIGURE 22.12 Applying styles to different menu levels
LISTING 22.15 MenuLevelStyles.aspx
<%@ Page Language=”C#” %>
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.1//EN”
“http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” >
<head id=”Head1” runat=”server”>
Trang 10<style type=”text/css”>
.menuLevel1
{
font:40px Arial,Sans-Serif;
}
.menuLevel2
{
font:20px Arial,Sans-Serif;
}
.menuLevel3
{
font:10px Arial,Sans-Serif;
}
</style>
<title>Menu Level Styles</title>
</head>
<body>
<form id=”form1” runat=”server”>
<div>
<asp:Menu
id=”Menu1”
Runat=”server”>
<LevelMenuItemStyles>
<asp:MenuItemStyle CssClass=”menuLevel1” />
<asp:MenuItemStyle CssClass=”menuLevel2” />
<asp:MenuItemStyle CssClass=”menuLevel3” />
</LevelMenuItemStyles>
<Items>
<asp:MenuItem Text=”Produce”>
<asp:MenuItem Text=”Apples” />
<asp:MenuItem Text=”Oranges” />
</asp:MenuItem>
<asp:MenuItem Text=”Beverages”>
<asp:MenuItem Text=”Soda”>
<asp:MenuItem Text=”Coke” />
<asp:MenuItem Text=”Pepsi” />
</asp:MenuItem>
</asp:MenuItem>
</Items>
</asp:Menu>
</div>
</form>
</body>
</html>