Элементы шаблонов в ASP.NET WebForms, нетривиальный data binding
WebForms задумывался для создания кода, обрабатывающего события пользовательского интерфейса, однако
в некоторых случаях бывает необходимо отойти от этой парадигмы и использовать кодовые вставки <%...%> в .aspx-файлах
почти в стиле ASP.NET MVC.
Встроенные компоненты, использущие т.н. data binding тоже иногда заставляют задуматься :)
Регистрация namespace'ов
Для того, чтобы сократить запись кода в .aspx-файлах бывает удобно импортировать неймспейсы (аналог using для code-behind).
Сделать это можно на уровне страницы:
<%@ Import Namespace="CrispStudio.Routine" %>
Либо для всех страниц сайта в Web.config:
<pages>
<controls>
<!-- А здесь можно зарегистрировать сторонние контролы, не добавляя их в Toolbox -->
</controls>
<namespaces>
<add namespace="CrispStudio.Routine"/>
...
</namespaces>
</pages>
Назначение свойств внутри data binding controls
<asp:LinkButton ID="lbDelete" runat="server"
OnClientClick="return confirm('Вы уверены, что хотите удалить этот раздел?');"
CommandName="remove"
CommandArgument='<%# ((Folder)Container.DataItem).NFolder %>'>
<img src="Images/Admin/delete.png" width="16" height="16" alt="Удалить" title="Удалить" />
</asp:LinkButton>
Вложенные контролы
В данном случае это GridView, завёрнутый в web user control внутри Repeater'a
<asp:Repeater ID="rSummary" runat="server" EnableViewState="False" OnItemDataBound="rSummary_ItemDataBound">
<ItemTemplate>
...
<uc2:GridControl ID="GridControlInner" runat="server" />
...
</ItemTemplate>
protected void rSummary_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if ((item.ItemType == ListItemType.Item) ||
(item.ItemType == ListItemType.AlternatingItem))
{
Web_Controls_GridControl grid = (Web_Controls_GridControl)item.FindControl("GridControlInner");
grid.DataSource = ...;
}
}
Биндинг коллекции объектов
В данном случае коллекция объектов типа TextPage:
<asp:Repeater ID="rTextPage" runat="server">
<ItemTemplate>
<h1><%# ((TextPage)Container.DataItem).TextPageTitle %>
<asp:PlaceHolder ID="cphEdit" runat="server" Visible="<%#WebUser.IsContentAdmin %>">
<!-- Ссылка на админку, которая видна для соответствующих пользователей -->
</asp:PlaceHolder>
</h1>
<%# ((TextPage)Container.DataItem).TextPageText %>
</ItemTemplate>
</asp:Repeater>
В этом же примере один из вариантов управления показом части контента по условию.
Использование Repeater'a для одного элемента
Этот удобный контрол можно использовать как простой шаблонизатор и в том случае, когда элемент всего один:
rTextPage.DataSource = new TextPage[] {currentPage};
rTextPage.DataBind();
Простая проверка по условию (спасибо ASP.NET MVC :))
<% if (HideLogoLink) { %>
<img src="images/logo.jpg" width="196" height="126" alt="Логотип"/>
<% } else { %>
<a href="..."><img src="images/logo.jpg" width="196" height="126" alt="Логотип"/></a>
<% } %>
Использование тернарного оператора (hardcore-версия)
<img src="<%# ( ((Good)Container.DataItem).GoodImageType != null && ((Good)Container.DataItem).GoodImageType != String.Empty) ? String.Format(Resources.General.ImageGoodsUrlThumb, Resources.General.UploadFolder, Resources.General.ImageTypeGoods, ((Good)Container.DataItem).NGood, ((Good)Container.DataItem).GoodImageType) : "Images/good_no_image.jpg" %>" alt="<%# ((GoodCustom)Container.DataItem).Producer.ProducerName%> <%# ((GoodCustom)Container.DataItem).GoodName %>" />
Определение функций в .aspx-файлах
Иногда удобно определить функцию прямо в шаблоне (например, если она будет использоваться один раз), главное — не увлекаться:
<script runat=server>
protected string doSomeStuff(object tempObj)
{
return tempObj.ToString();
}
</script>
<asp:Repeater ID="rFirstLevel" runat="server" EnableViewState="false">
<ItemTemplate>
<%# doSomeStuff(Container.DataItem) %>
</ItemTemplate>
</asp:Repeater>
Номер итерации в data binding conrol'e
<%#Container.ItemIndex %>
HTML в заголовке колонки GridView при использовании ASP.NET CSS Adapters
<asp:TemplateField HeaderText='<div style="text-align: right">Цена</div>'>
Биднинг Dictionary
<%# Eval("key") %>
<%# Eval("value") %>
Проверка наличия данных в Repeater
Вариант 1:
<% noResuts.Visible = (rResults.Items.Count > 0); %> <asp:PlaceHolder ID="noResuts" runat="server"> Нет результатов </asp:PlaceHolder> <asp:Repeater ID="rResults" runat="server"> <ItemTemplate> ... </ItemTemplate> <asp:Repeater>
Вариант 2:
<% if (rResults.Items.Count == 0) { %>
Нет результатов
<% } %>
<asp:Repeater ID="rResults" runat="server">
<ItemTemplate>
...
</ItemTemplate>
<asp:Repeater>
Использование <%=..%> внутри data binding контролов
Напрямую блоки кода, отличные от <%#..%> вставлять внутрь data binding контролов не разрешается. Решение простое, нужно вставить внутрь data binding контрола контрол PlaceHolder.
