Основы ASP.NET 2.0

         

Элемент управления Menu


Выпадающее меню можно создать средствами одного только css. Это красивое решение, но требует большого объема кода. Также необходимо предусмотреть возможность просмотра разными браузерами. Большинство разработчиков создают меню с помощью JavaScript. В ASP .NET 2.0 создание выпадающего меню любого уровня вложенности требует всего двух строчек:

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /> <asp:Menu ID="Menu1" runat="server" DataSourceID="SiteMapDataSource1"></asp:Menu>

Вся остальная работа достается ASP .NET. А ее будет много! Чтобы убедиться в этом, посмотрите сгенерированный код в браузере.

Menu идеален для отображения большого количества иерархической информации. Занимая мало места, узлы меню раскрываются при наведении курсора мыши. Стрелка рядом с пунктом меню означает, что в нем есть подменю. Вместо стрелки можно использовать изображение, задав свойство DynamicPopOutImageUrl. Картинки также можно задействовать в качестве разделителей между пунктами меню.

Menu допускает горизонтальную и вертикальную ориентацию, которая задается свойством Orientation. При горизонтальной ориентации можно получить полоску меню. Меню состоит из статической и динамической частей, каждый — со своим набором стилей.

StaticHoverStyleDynamicHoverStyle
StaticMenuItemStyleDynamicMenuItemStyle
StaticMenuStyleDynamicMenuStyle
StaticSelectedStyleDynamicSelectedStyle
StaticTemplateDynamicTemplate

Стили можно поменять "одним махом" с помощью автоформатирования.


Статические пункты отображаются постоянно, а динамические — при выборе родительских узлов. Для этого автоматически генерируется код JavaScript.

Свойство StaticDisplayLevels по умолчанию равно 1, то есть показываются только главные пункты меню, а остальные появляются в момент наведения мышки. Если это значение изменить, получим статическое многоуровневое меню. На странице разные меню можно привязать к разным источникам SiteMapDataSource, тогда при одной карте сайта они будут показывать его разные подмножества:

<?xml version="1.0" encoding="utf-8" ?> <siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File- 1.0" > <siteMapNode title="Main" > <siteMapNode title=" Главная" url="Default.aspx"> <siteMapNode url="courses.aspx" title="Курсы" descrip- tion="Курсы" /> <siteMapNode url="speciality.aspx" title="Учебные программы" description="" /> <siteMapNode url="shop.aspx" title="Учебники" description="" /> <siteMapNode url="News.aspx" title="Новости" description="" /> <siteMapNode url="Forum.aspx" title="Форум"/> <siteMapNode url="Help.aspx" title="Помощь"/> </siteMapNode> <siteMapNode title="user" url="Default2.aspx"> <siteMapNode url="login.aspx" title="Регистрация" description="" /> <siteMapNode title="||" > <siteMapNode url="records.aspx" title="Зачетка" description="" /> <siteMapNode url="diploms.aspx" title="Дипломы" description="" /> </siteMapNode> <siteMapNode title="||" > <siteMapNode url="user.aspx" title="Настройки" description="" /> <siteMapNode url="cart.aspx" title="Корзина"/> <siteMapNode url="history.aspx" title="Заказы"/> <siteMapNode url="account.aspx" title="Личный счет"/> </siteMapNode> </siteMapNode> </siteMapNode> </siteMap>



Одно меню должно показывать разделы сайта, второе — возможности пользователя:

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" ShowStartingNode="False" StartingNodeUrl="~/Default.aspx" /> <asp:Menu ID="Menu1" runat="server" BackColor="#FFFBD6" DataSourceID="SiteMapDataSource1" DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#990000" StaticSubMenuIndent="10px" Orientation="Horizontal"> <StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" /> <DynamicHoverStyle BackColor="#990000" ForeColor="White" /> <DynamicMenuStyle BackColor="#FFFBD6" /> <StaticSelectedStyle BackColor="#FFCC66" /> <DynamicSelectedStyle BackColor="#FFCC66" /> <DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" /> <StaticHoverStyle BackColor="#990000" ForeColor="White" /> </asp:Menu> <asp:SiteMapDataSource ID="SiteMapDataSource2" runat="server" ShowStartingNode="False" StartingNodeUrl="~/Default2.aspx" /> </div> <asp:Menu ID="Menu2" runat="server" DataSourceID="SiteMapDataSource2" Orientation="Horizontal" BackColor="#F7F6F3" DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#7C6F57" StaticSubMenuIndent="10px" StaticDisplayLevels="2"> <StaticMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" /> <DynamicHoverStyle BackColor="#7C6F57" ForeColor="White" /> <DynamicMenuStyle BackColor="#F7F6F3" /> <StaticSelectedStyle BackColor="#5D7B9D" /> <DynamicSelectedStyle BackColor="#5D7B9D" /> <DynamicMenuItemStyle HorizontalPadding="5px" VerticalPadding="2px" /> <StaticHoverStyle BackColor="#7C6F57" ForeColor="White" /> </asp:Menu>



Пункты меню могут быть описаны на странице, а также добавлены программно:

<asp:Menu ID="Menu3" runat="server" BackColor="#B5C7DE" DynamicHorizontalOffset="2" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#284E98" StaticDisplayLevels="3" StaticSubMenuIndent="30px"> <Items> <asp:MenuItem Text="Настройки" Value="Настройки" Selectable="false" > <asp:MenuItem Text="Анкета" Value="Анке- та"></asp:MenuItem> <asp:MenuItem Text="Подписка" Value="Подпи- ска"></asp:MenuItem> <asp:MenuItem Text="Пароль" Value="Па- роль"></asp:MenuItem> </asp:MenuItem> </Items> </asp:Menu>

Когда элемент управления привязан к карте сайта, то пункты меню представляют собой гиперссылки на страницы. Событие MenuItemClick позволяет определить поведение страницы при выборе пунктов меню, когда он заполняется другими способами, например через XmlDataSource. В параметре MenuEventArgs находится информация и о выбранном пункте, и о родительском узле:

<script runat="server"> protected void Menu1_MenuItemClick(object sender, MenuEventArgs e) { Listbox1.Items.Add(e.Item.Parent.Value + " : " + e.Item.Value); } </script>


Элемент управления SiteMapPath


Подобную панель, которая показывает путь от главной страницы к текущей, часто называют breadcrumb ("хлебные крошки"):

MSDN Home > ASP.NET Developer Center > Reference > Using ASP.NET Controls

Вероятно, это связано со сказкой о Мальчике-с-Пальчик, который бросал хлебные крошки по пути в лес, чтобы найти путь домой. Пользователь большого и сложного web-узла тоже должен знать, где он находится, и не потеряться в лабиринте. Поэтому можно назвать этот элемент еще и нитью Ариадны. Он состоит из последовательности гиперссылок на все вышестоящие узлы сайта. Текущая страница отображена простым текстом. Эту настройку можно изменить, установив свойство RenderCurrentNodeAsLink в True.

Для того чтобы на странице работал этот элемент, даже не нужно источника данных. Он автоматически читает карту сайта из файла Web.sitemap. Достаточно просто перетащить его на страницу. Имеются 4 свойства стиля, каждый из которых задается отдельно: для корневого элемента, для разделителя, обычного узла и текущего узла. У SiteMapPath имеется такая же возможность автоформатирования, как и у многих других элементов управления.

Свойство PathDirection позволяет изменить направление от корня к текущей странице на обратное. Например, если путь у вас был таким:

Главная : Игра : Таблица,

то после изменения значения PathDirection на CurrentToRoot станет таким:

Таблица : Игра : Главная

Текстовый атрибут PathSeparator задает разделитель между узлами. Например, в первом примере это " > ", который ставится по умолчанию, а во втором " : ".




Пробелы здесь существенны. Похожие атрибуты были и в календаре — к примеру NextMonthText. Для того чтобы задать изображения, в качестве разделителя можно использовать шаблон PathSeparatorTemplate:

<asp:SiteMapPath ID="SiteMapPath1" runat="server"> <PathSeparatorTemplate> <asp:Image ID="Image1" runat="server" ImageUrl="img/fold- er.gif" /> </PathSeparatorTemplate> </asp:SiteMapPath>

Свойство ParentLevelsDisplayed позволяет ограничить количество отображаемых родительских узлов. Если оно равно - 1 (по умолчанию), то показываются все узлы.

Если подержать курсор мыши над элементом, появится подсказка, текст которой берется из атрибута description соответствующего узла карты сайта. Отключить отображение подсказки можно с помощью свойства ShowToolTips="false".

Всего имеется 4 шаблона: PathSeparatorTemplate, NodeTemplate, RootTemplate и CurrentNodeTemplate, с помощью которых можно вставлять любые элементы управления в различные части SiteMapPath. Для каждой из частей можно определить и собственный стиль.


Программное управление TreeView


У TreeView есть множество событий. Событие SelectedNodeChanged запускается, когда пользователь выбирает узел:

protected void TreeLibrary_SelectedNodeChanged(object sender, EventArgs e) { Label1.Text = "Вы выбрали категорию " + TreeLibrary.SelectedNode.Text; }

Можно программно раскрывать и закрывать узлы:

TreeView1.ExpandAll(); TreeView1.CollapseAll();

Событие TreeNodePopulate позволяет динамически заполнять узлы, при этом можно экономить память, если заполнять узлы только по требованию после раскрытия родительского узла. Событие TreeNodePopulate вызывается, если действие (например, раскрытие) проведено с узлом, у которого SelectAction настроен на это действие.

В следующем примере заполним значения элемента управления TreeView из базы данных Northwind. Родительские узлы — категории продуктов, которые заполняются данными о продуктах тогда, когда узел необходимо раскрыть:

<asp:TreeView ID="TreeViewCatProd" runat="server" ImageSet="BulletedList3" OnTreeNodePopulate="TreeViewCatProd_TreeNodePopulate" ForeColor="DarkOliveGreen"> </asp:TreeView>

public partial class Products : System.Web.UI.Page { string connectionString = @"Data Source=.\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True";

protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { BindData(); } }

Вспомогательная функция устанавливает соединение с базой данных и возвращает SqlDataReader — самый быстрый способ чтения данных:


protected SqlDataReader CreateSqlDataReader(string SelectQuery, string ConnectionString) { SqlConnection Connection = new SqlConnection(ConnectionString); SqlCommand Command = new SqlCommand(SelectQuery, Connection); try { Command.CommandType = CommandType.Text; Command.Connection.Open(); SqlDataReader reader = Command.ExecuteReader(CommandBehavior.CloseConnection); return reader; } catch { Connection.Close(); return null; } }

При работе с базами данных важно перехватывать исключения:

protected void BindData() { TreeNode parentNode = null; SqlDataReader reader = CreateSqlDataReader("Select CategoryID,CategoryName from Categories", connectionString); if (reader!=null) { while (reader.Read()) { parentNode = new TreeNode(reader["CategoryName"].ToString(), reader["CategoryID"].ToString()); parentNode.Collapse(); parentNode.PopulateOnDemand = true; parentNode.SelectAction = TreeNodeSelectAction.Expand; TreeViewCatProd.Nodes.Add(parentNode); } reader.Close(); } }

Конструктор TreeNode может вызываться без параметров, но он перегружен. Вариант, который здесь используется, позволяет задать текст узла и значение Value (заполняется значением CategoryID), которое необходимо, чтобы найти в базе продукты этой категории.

При раскрытии узла с категорией будет вызываться обработчик:

protected void TreeViewCatProd_TreeNodePopulate(object sender, TreeNodeEventArgs e) { TreeNode node = e.Node; if (node.PopulateOnDemand) { string command = string.Format("Select ProductID, ProductName from Products where CategoryID={0}", node.Value); SqlDataReader reader = CreateSqlDataReader(command, connectionString); node.ChildNodes.Clear(); if (reader != null) { while (reader.Read()) { TreeNode childNode = new TreeNode(reader["ProductName"].ToString()); childNode.SelectAction = TreeNodeSelectAction.None; node.ChildNodes.Add(childNode); } node.Expand(); reader.Close(); } } }



TreeView позволяет не только показывать информацию, но ставить флажки рядом с узлами. Это полезно, если в нем содержится информация о товарах и пользователь может выбрать некоторые из них. Свойство ShowCheckBoxes допускает 5 значений: None, Root, Parent, Leaf, All:

ShowCheckBoxes="Leaf"

При этом рядом с узлами-листьями появляются флажки. Значение флажков можно прочитать программно:

<asp:XmlDataSource ID="XmlDataSource3" runat="server" DataFile="~/menu.xml"></asp:XmlDataSource> <asp:TreeView ID="TreeMenu" runat="server" DataSourceID="XmlDataSource3" BackColor="#FFFBD6" Font-Names="Verdana" Font-Size="0.8em" ForeColor="#990000" Height="78px" Width="415px" ShowCheckBoxes="Parent" OnTreeNodeCheckChanged="TreeMenu_TreeNodeCheckChanged" NodeWrap="True" PopulateNodesFromClient="False"> <DataBindings> <asp:TreeNodeBinding DataMember="name" ValueField="#InnerText" /> <asp:TreeNodeBinding DataMember="price" FormatString="{0} руб." TextField="#InnerText" ValueField="#InnerText" /> <asp:TreeNodeBinding DataMember="description" TextField="#InnerText" /> <asp:TreeNodeBinding DataMember="calories" FormatString="{0} калорий" TextField="#InnerText" /> <asp:TreeNodeBinding DataMember="food" TextField="name" /> <asp:TreeNodeBinding DataMember="pizza_menu" Text="Меню Пиццы" Value="Меню Пиццы" /> </DataBindings> </asp:TreeView> <asp:Label ID="Label1" runat="server" ></asp:Label>



Флажки стоят у родительских узлов, потому что именно там находятся названия блюд. В обработчике можно динамически показывать сумму текущего заказа:

protected void TreeMenu_TreeNodeCheckChanged(object sender, TreeNodeEventArgs e) { decimal sumPrices=0.0M; if (TreeMenu.CheckedNodes.Count > 0) { Label1.Text = ""; foreach (TreeNode node in TreeMenu.CheckedNodes) { sumPrices += decimal.Parse(node.ChildNodes[0].Value); } Label1.Text = sumPrices.ToString() +"<br>"; } }

Цена записана в первом дочернем поле с индексом 0. При этом обращаться к свойству Text было бы неправильно, потому что там находится отформатированный текст, например, "306 руб.", который нельзя преобразовать в число.


SiteMapDataSource


Источник данных SiteMapDataSource работает с помощью провайдера SiteMapProvider. Этот источник данных не поддерживает кэширование, как другие. Он может быть связан только с файлом карты сайта.

В простейшем виде объявляется так:

<asp:SiteMapDataSource ID="SiteMapDataSource1" Runat="server" />

Свойство ShowStartingNode определяет, будет ли элемент читать корневой узел карты сайта. Если свойство не установлено, то в коллекцию узлов попадут только дочерние элементы корневого узла.

StartFromCurrentNode =False задает возможность читать только узлы, начиная с текущей страницы.

Свойство FlatDepth задает количество уровней вложенности, которое читается из карты сайта. По умолчанию это - 1, то есть читаются все доступные уровни.

SiteMapProvider может быть полезным при написании собственных провайдеров карты сайта.

SiteMapViewType определяет форму представления узлов. По умолчанию это Tree. Если значение равно Path, то будет читаться путь между корневым узлом и текущим, как в элементе управления SiteMapPath.



TreeView


Элемент TreeView создан специально для показа иерархической информации. Он может черпать информацию как из любого XML-файла через XmlDataSource, так и из карты сайта посредством SiteMapDataSource. Как следует из его названия, TreeView показывает данные в виде дерева, причем его узлы можно раскрывать и закрывать, выбирать отдельные "листья". При этом будут запускаться события, которые можно обработать.

TreeView состоит из узлов, которые соединены между собой отношениями "родитель—потомок". У одного родителя может быть один или несколько потомков. Узлы, у которых нет родителя, называются корневыми. Их в элементе управления может быть несколько. Узлы, у которых нет потомков, называются листьями.

При декларации TreeView на странице узлы описываются тегами TreeNode. Допускается любой уровень вложенности узлов друг в друга. Узлы элемента управления можно редактировать визуально:

<asp:TreeView ID="TreeLibrary" runat="server" ImageSet="WindowsHelp" > <Nodes> <asp:TreeNode Text="Категории книг" Value="Book Categories"> <asp:TreeNode Text="Художественная литература" Value="literature"> <asp:TreeNode Text="Русская классика" Value="Russian Classics" NavigateUrl="~/libru.aspx?id=1"> <asp:TreeNode Text="Пушкин" Value="Pushkin" NavigateUrl="~/libru.aspx?id=1&auth=10"> </asp:TreeNode> </asp:TreeNode> </asp:TreeNode> <asp:TreeNode Text="Компьютерная литература" Value="Computers"> <asp:TreeNode Text="Web Development" Value=" Web Development" NavigateUrl="~/example1.aspx?id=1"> <asp:TreeNode Text="JavaScript" Value=" JavaScript " NavigateUrl="~/example1.aspx?id=2"> </asp:TreeNode> <asp:TreeNode Text="ASP.NET" Value="ASP.NET" NavigateUrl="~/example1.aspx?id=3"></asp:TreeNode> </asp:TreeNode> </asp:TreeNode> </asp:TreeNode> </Nodes> </asp:TreeView>


Если нужно программно добавлять дочерние узлы, свойство PopulateOnDemand нужно установить в True.

Внешний вид TreeView можно менять самым разнообразным способом. Можно включить показ линий, соединяющих узлы:

ShowLines="True"

Внешний вид линий можно отредактировать, при этом с помощью средства TreeView Line Generator будут созданы изображения для всех ее фрагментов.

Вместо текста в узлах можно показывать изображения, заданные свойством ImageUrl.

Свойство ImageSet имеет набор предопределенных значков для разных типов узлов. Например, MSDN придаст вашему дереву сходство с TreeView на сайте msdn.com, а XPFileExplorer — с программой Explorer в Windows XP.


Рис. 11.1. 

В качестве изображения для узлов можно задать любые картинки:

CollapseImageUrl="Images/CollapseImage.gif" ExpandImageUrl="Images/ExpandImage.gif" LeafImageUrl=Images/LeafImage.gif">

Если источником данных служит XmlDataSource, то его узлы можно привязать к элементу TreeView. Создайте на странице TreeView. У него есть "умный ярлык", который позволит настроить источник данных. Настройка происходит так же, как и у элемента управления Xml.


Рис. 11.2. 

После этого нужно настроить способы показа данных. По умолчанию он будет показывать названия узлов, а не их внутреннее содержание. В SmartTag выберите пункт Edit TreeNode Databindings. В результате в редакторе должен появиться примерно такой текст:

<asp:XmlDataSource ID="XmlDataSource1" runat="server" DataFile="~/FilmChoices.xml" XPath="FilmChoices/Film"></asp:XmlDataSource> <asp:TreeView ID="TreeView1" runat="server" DataSourceID="XmlDataSource1" Width="405px"> <DataBindings> <asp:TreeNodeBinding DataMember="Film" TextField="Title" /> <asp:TreeNodeBinding DataMember="Year" FormatString="Год {0}" TextField="#InnerText" /> <asp:TreeNodeBinding DataMember="Director" FormatString="Режиссер {0}" TextField="#InnerText" /> </DataBindings> </asp:TreeView>



Значение TextField используется, если нужно показать значения атрибутов узла в исходном XML-файле, а #InnerText указывает текст между открывающими и закрывающими тегами узла.

Если выбираем источником данных SiteMap, то на странице создается еще один элемент управления — SiteMapDataSource:

<asp:SiteMapDataSource ID="SiteMapDataSource1" runat="server" /> <asp:TreeView ID="TreeView1" runat="server" DataSourceID="SiteMapDataSource1" ShowLines="True" BackColor="WhiteSmoke" BorderStyle="Outset" ImageSet="BulletedList" Font-Names="Verdana" Font- Overline="False" ForeColor="#804040" Width="199px" > </asp:TreeView>

На странице элемент TreeView будет выглядеть так:


Рис. 11.3. 

Содержательная часть этого меню находится в файле карты сайта, а форматирование производится в свойствах TreeView. Свойство AutoGenerateDataBindings позволяет автоматически заполнять узлы информацией из карты сайта.


Широкие возможности системы навигации ASP


Широкие возможности системы навигации ASP .NET 2.0 позволяют отделить логическое представление карты сайта от его визуального представления, сэкономить время на разработку.