Создание веб-частей
161ASP.NET --- Веб-сайты ASP.NET --- Создание веб-частей
Теперь, когда известно, какие шаги необходимо выполнить для создания страниц веб-частей в ASP.NET, стоит взглянуть внимательнее на разработку веб-частей. Как вы знаете, веб-частью может быть любой элемент управления ASP.NET, включая пользовательские элементы управления, встроенные или специальные серверные элементы управления и элементы управления ASP.NET, напрямую унаследованные от базового класса WebPart из пространства имен System.Web.UI.WebControls.WebParts.
Вы уже видели, что каждая веб-часть на странице автоматически получает заголовок и меню по умолчанию для своего сворачивания и восстановления. Теперь давайте посмотрим, как можно настроить текст заголовка и добавить пункты меню (называемые командами (verb)) к специальной веб-части.
Любая веб-часть может предоставлять специальные общедоступные свойства, которые пользователь может модифицировать в веб-части редактора, добавляемой к EditorZone. Зона EditorZone отображается, когда страница веб-частей переключается в режим Edit. Для этого понадобится создать отдельную часть редактора для веб-части и каким-то образом соединить их. В следующем разделе показано, как это делать.
В конечном итоге веб-части могут взаимодействовать с другими веб-частями через четко определенный механизм. Таким образом, эти веб-части передают данные и отображают информацию на основе событий, которые происходят в других веб-частях.
Простые задачи с веб-частями
Вы уже знаете, что простейший способ конструирования пользовательских веб-частей - создание пользовательских элементов управления. Единственное отличие состоит в том, что вместо помещения прямо на страницу эти элементы управления добавляются в раздел ZoneTemplate зоны веб-частей. По сути, ASP.NET Web Parts Framework помещает ваш пользовательский элемент управления в оболочку экземпляра GenericWebPart. Этот класс GenericWebPart гарантирует, что пользовательский элемент управления получает фрейм и команды меню для сворачивания и восстановления веб-части. То же самое верно и в отношении любого серверного элемента управления (как готового, так и специального): если только элемент управления ASP.NET не унаследован напрямую от System.Web.UI.WebControls.WebParts.WebPart, платформа Web Parts Framework помещает его в оболочку экземпляра GenericWebPart.
Если вы хотите получить доступ к свойствам и событиям элементов управления, которые были добавлены на страницу в качестве веб-частей, то можете сделать это обычным образом. Например, чтобы перехватить событие Calendar.SelectedDateChanged ранее созданной страницы с веб-частями, дважды щелкните на элементе Calendar в визуальном конструкторе Visual Studio. Ниже представлен пример установки свойства SelectedDate ранее добавленного элемента управления Calendar при первом запросе страницы:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
// Это странный обходной маневр для календаря
// Но это единственный способ заставить его работать независимо
// от того, является он частью зоны веб-частей или нет...
Calendar helper = new Calendar();
helper.SelectedDate = DateTime.Now.AddDays(30);
helper.VisibleDate = DateTime.Now.AddDays (30);
MyCalendar.SelectedDate = DateTime.Now.AddDays(7);
MyCalendar.VisibleDate = helper.VisibleDate;
}
}
Итак, вы имеете полный доступ к элементам управления, добавленным как веб-части, и не должны для этого предпринимать ничего особенного. Но что если нужно получить доступ к специфичным для веб-частей свойствам, таким как заголовок или события веб-части?
Как уже упоминалось, каждая веб-часть, которая не унаследована от WebPart, автоматически помещается в оболочку экземпляра GenericWebPart. Чтобы обратиться к специфичным для веб-частей свойствам, понадобится каким-то образом извлечь веб-часть и затем установить или получить необходимые свойства. К счастью, класс WebPartManager включает свойство типа коллекции WebParts, которое содержит все веб-части, доступные странице. Преимущество от обращения к веб-частям напрямую через WebPartManager состоит в том, что вы не обязаны знать, к какой зоне они были добавлены (вспомните, что пользователь может это при желании изменить).
В следующем примере коллекция WebParts, принадлежащая WebPartManager, используется для итерации по веб-части, при этом каждой веб-части, которая была помещена в оболочку GenericWebPart, присваивается заголовок по умолчанию:
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
int i = 1;
foreach (WebPart part in WebPartManager1.WebParts)
{
if (part is GenericWebPart)
part.Title = string.Format("Web Part № {0} ", i);
i++;
}
}
}
С помощью свойств веб-части можно также изменять и другие аспекты. В таблице ниже описаны некоторые типичные примеры и представлен обзор наиболее важных свойств элемента управления WebPart:
Свойства | Описание |
---|---|
AllowClose | Указывает, может ли веб-часть быть закрыта пользователем. Если установлено в false, пункт меню Close (Закрыть) не отображается в меню веб-части |
AllowConnect | Разрешает или запрещает функциональность подключения веб-части |
AllowEdit | Разрешает или запрещает свойства редактирования веб-части с помощью EditorPart |
AllowHide | Если установлено в true, пользователь может скрывать веб-часть на странице |
AllowMinimize | Если установлено в true, пользователь может сворачивать веб-часть через пункт меню |
AllowZoneChange | Если пользователь должен иметь возможность изменить позицию веб-части, перетаскивая ее из одной WebPartZone в другую, это свойство должно быть установлено в true, иначе - в false (по умолчанию равно true) |
CatalogIconImageUrl | Как было показано ранее, PageCatalogPart отображает список веб-частей, доступных на странице. Если хотите добавить специальный значок для отображения в PageCatalogPart из CatalogZone, можете установить в CatalogIconImageUrl подходящее изображение |
ChromeType | Настраивает внешний вид. Можно указать, должна ли веб-часть иметь рамку, заголовок и команды меню, содержащие действия для сворачивания или закрытия веб-части. Это свойство имеет тип PartChromeType, который поддерживает значения None, BorderOnly, TitleOnly, TitleAndBorder и Default |
ChromeState | Определяет начальный внешний вид веб-части. Свойство имеет тип PartChromeState и может принимать значения Minimized или Normal, так что WebPart изначально будет свернутой или отображенной |
ConnectErrorMessage | Указывает сообщение об ошибке, отображаемое в случая неудачи подключения одной WebPart к другой. Такое случается, когда целевая веб-часть генерирует исключение при подключении к другой веб-части |
Controls | Эта важная коллекция предоставляет доступ ко всем элементам управления внутри веб-части. Ниже вы узнаете об этом подробнее |
Description | Указывает дружественное к пользователю описание веб-части |
Direction | Указывает направление потока содержимого внутри WebPart (LeftToRight или RightToLeft). Если оставить значение по умолчанию NotSet, будет использовано значение по умолчанию для текущей культуры |
DisplayTitle | Получает строку, которая возвращает заголовок, отображаемый в веб-части в данный момент. Если свойство Title не установлено, то возвращается либо автоматически сгенерированный заголовок, либо заголовок содержащегося внутри элемента управления |
ExportMode | Информация и настройки веб-части могут быть экспортированы и импортированы. Это свойство указывает, какие именно фрагменты веб-части могут быть экспортированы либо импортированы |
HasSharedData | Указывает, содержит ли веб-часть персонализированные свойства, которые сохраняются для множества пользователей |
HasUserData | Указывает, содержит ли веб-часть персонализированные свойства, которые сохраняются для каждого пользователя в отдельности |
HelpUrl | Свойством HelpUrl можно указывать URL-адрес, возвращающий содержимое, которое должно отображаться в качестве подсказки для веб-части. Может указывать либо на статическую HTML-страницу, либо на страницу любого другого типа, включая .aspx. Если этот URL-адрес установлен, веб-часть отображает дополнительный пункт меню для открытия подсказки к этой веб-части |
HelpMode | Когда установлено свойство HelpUrl, можно определить, где именно должна отображаться подсказка. Она может отображаться в модальном или немодальном всплывающем окне, или же можно задать прямую навигацию на страницу справки |
Hidden | Получает или устанавливает значение, определяющее, будет ли веб-часть скрытой |
IsClosed | Получает или устанавливает значение, определяющее, закрыта ли веб-часть |
IsShared | Получает или устанавливает значение, определяющее, должна ли веб-часть быть видимой всем пользователям или только определенному пользователю |
IsStandalone | Определяет, должна ли веб-часть содержаться в WebPartZone (false) или быть автономной веб-частью, не принадлежащей WebPartZone (true) |
IsStatic | Получает или устанавливает значение, которое определяет, добавлена ли веб-часть к странице статически с помощью визуального конструктора (true) или динамически импортирована в веб-страницу (это означает, что она добавлена на страницу программно) |
Title | Получает или устанавливает заголовок, отображаемый в панели заголовка |
TitleUrl | Заголовок может быть отображен как URL-адрес, указывающий на страницу деталей веб-части. Если этот URL-адрес задан, веб-часть визуализирует заголовок как ссылку, указывающую на этот URL, а не как статический текст |
Verbs | Возвращает пункты меню веб-части, которые обычно содержат Minimize (Свернуть), Close (Закрыть) и Help (Справка). Эти пункты можете настроить, модифицируя коллекцию |
Zone | Возвращает ссылку на WebPartZone, к которой в данный момент добавлена веб-часть |
ZoneIndex | Возвращает индекс WebPartZone, к которому в данный момент добавлена веб-часть |
Как упоминалось в таблице ниже, коллекция Controls элемента управления WebPart содержит все элементы, добавленные к WebPartZone. Поэтому можно выполнить итерацию по всем элементам управления WebPart, сохраненным в коллекции Controls, найти конкретный элемент и что-то с ним сделать. В следующем примере показано, как обращаться к элементам управления всей страницы ASP.NET (через элемент WebPartManager, добавленный к странице) для установки свойств веб-части, которая содержит ранее добавленный элемент Calendar:
foreach (WebPart part in WebPartManager1.WebParts)
{
if (part.Controls.Contains(MyCalendar))
{
part.AllowClose = false;
part.HelpMode = WebPartHelpMode.Modeless;
part.HelpUrl = "CalendarHelp.html";
}
}
Элементы управления, добавленные к WebPartZone, доступны непосредственно изнутри страницы. Поэтому, если необходимо установить специфичные для веб-части свойства при загрузке страницы, то можете сделать это с помощью другого, обходного пути. Вместо итерации по коллекции WebParts в WebPartManager с последующим обращением к коллекции Controls каждой веб-части, может быть, быстрее перехватить события элемента управления и затем обратиться к свойствам веб-части через свойство Parent этого элемента, примерно так:
protected void MyCalendar_Load(object sender, EventArgs e)
{
GenericWebPart part = (GenericWebPart)MyCalendar.Parent;
part.AllowClose = false;
part.HelpMode = WebPartHelpMode.Modeless;
part.HelpUrl = "CalendarHelp.html";
}
Это определенно быстрее, чем поиск элементов управления в коллекциях элементов, как было показано ранее.
Предыдущий пример выполняет ту же работу по инициализации, что показана в другом примере - отключает функцию закрытия для веб-части, которая содержит календарь MyCalendar, и затем указывает страницу справки для календаря, которая может быть отображена в немодальном всплывающем окне браузера. Результат этих модификаций показан на рисунке ниже:
Взгляните внимательно на меню, отображенное для веб-части. Поскольку свойство HelpUrl было инициализировано, теперь оно включает в себя дополнительный пункт Help (Справка). С другой стороны, т.к. свойство AllowClose установлено в false, пункт меню Close (Закрыть) отсутствует.
Обратите внимание, что окно справки, которое видно на рисунке - это простая HTML-страница, отображаемая во всплывающем окне браузера. В этом можно удостовериться, просто взглянув на предыдущий фрагмент кода, где в качестве страницы справки задана CalendarHelp.html. Страница справки может быть также и динамической страницей, такой как страница ASP.NET, поскольку Web Parts Framework не делает ничего помимо добавления необходимого кода сценария клиентской стороны для открытия всплывающего окна, которое просто выполняет HTTP-запросы GET по URL-адресу, указанному в свойстве HelpUrl.
Реализация интерфейса IWebPart
До этого момента доступ к веб-частям происходил только извне. Но при создании пользовательского элемента управления, который должен применяться как веб-часть на странице веб-частей, можно также обращаться к свойствам веб-части изнутри пользовательского элемента управления. Реализация интерфейса IWebPart дает определенную степень управления внешним видом и поведением веб-части WebPart.
Интерфейс IWebPart определяет контракт между вашим элементом управления (серверным или пользовательским), применяемым классом оболочки GenericWebPart для взаимодействия с элементом с целью решения таких специфических задач, как автоматическое извлечение его заголовка, чтобы не нужно было устанавливать его внутри каждой страницы, в которой будет использоваться веб-часть. В таблице ниже описаны члены, которые должны присутствовать в веб-части, когда она реализует интерфейс IWebPart:
Свойство | Описание |
---|---|
CatalogIconImageUrl | Получает или устанавливает URL изображения, выводимого для веб-части в PageCatalogPart зоны CatalogZone |
Description | Получает или устанавливает строку, содержащую дружественное к пользователю описание веб-части |
Subtitle | Указывает дружественный к пользователю подзаголовок веб-части. Он соединяется с заголовком, содержащимся в свойстве Title веб-части |
Title | Указывает заголовок, отображаемый для веб-части. Когда это свойство задано, устанавливать заголовок извне, как было описано ранее, не понадобится |
TitleIconImageUrl | URL-адрес, который указывает на изображение, выводимое в виде значка внутри панели заголовка WebPart |
TitleUrl | URL-адрес, по которому должен перейти браузер, когда пользователь щелкает на заголовке веб-части. Если этот URL-адрес установлен, заголовок визуализируется в виде ссылки, а в противном случае - как статический текст |
Как видите, реализация этого интерфейса не требует слишком больших усилий. Реализовать IWebPart в ранее созданном элементе управления MyDataControl можно следующим образом:
public partial class MyDataControl : System.Web.UI.UserControl, IWebPart
{
private string _CatalogImageUrl;
public string CatalogIconImageUrl
{
get
{
return _CatalogImageUrl;
}
set
{
_CatalogImageUrl = value;
}
}
private string _Description;
public string Description
{
get
{
return _Description;
}
set
{
_Description = value;
}
}
public string Subtitle
{
get { return "Список наших клиентов"; }
}
private string _TitleImage;
public string TitleIconImageUrl
{
get
{
if (_TitleImage == null)
return "~/CustomersSmall.jpg";
else
return _TitleImage;
}
set
{
_TitleImage = value;
}
}
private string _TitleUrl;
public string TitleUrl
{
get
{
return _TitleUrl;
}
set
{
_TitleUrl = value;
}
}
public string Title
{
get
{
if (ViewState["Title"] == null)
return string.Empty;
else
return (string)ViewState["Title"];
}
set
{
ViewState["Title"] = value;
}
}
}
При реализации интерфейса IWebPart необходимо подумать о том, какие значения свойств должны быть помещены в состояние представления, а какие значения достаточно хранить в виде приватных членов. Для сокращения количества байт, передаваемых по сети вместе со страницей, в состояние представления нужно помещать как можно меньше информации. Состояние представления должно использоваться только для той информации, которая может быть изменена пользователем при просмотре, поэтому ее нельзя терять между обратными отправками.
В предыдущем примере для каждого свойства веб-части использовались приватные члены, но не для свойства заголовка, поскольку он может измениться в процессе просмотра (например, если необходимо отобразить текущую страницу GridView в панели заголовка). При реализации этого интерфейса информация (установленная извне) автоматически передается экземпляром GenericWebPart в реализацию вашего элемента управления. Рассмотрим код страницы Default.aspx, предполагая, что был добавлен экземпляр ранее созданного элемента управления MyDataControl, с событием Load которого ассоциирована следующая процедуру обработки:
protected void MyDataControl1_Load(object sender, EventArgs e)
{
// Некоторые свойства установлены; другие, подобные TitleImageUrl - нет
GenericWebPart part = (GenericWebPart)MyDataControl1.Parent;
part.Title = "Заказчик";
part.TitleUrl = "http://professorweb.ru";
part.Description = "Показаны все заказчики из базы данных!";
}
Когда некто подобным образом устанавливает заголовок веб-части извне, экземпляр GenericWebPart передает значение интерфейсной реализации свойства Title, так что эту информацию можно обработать. С другой стороны, если некто запрашивает такую информацию, как Title или TitleUrl, то GenericWebPart извлекает ее из вашего элемента управления, обращаясь к соответствующему свойству в реализации IWebPart. Таким образом, элемент управления может возвращать значения по умолчанию, даже если некоторые свойства не были явно установлены. Реализация TitleIconImageUrl именно это и делает. Это свойство возвращает URL-адрес изображения по умолчанию, если свойство TitleImage не было установлено. Это значит, что даже если не установить это свойство в ранее показанной процедуре события Load страницы с веб-частями, веб-часть будет отображать CustomersSmall.jpg в качестве изображения заголовка:
Хотя свойство TitleImageUrl не было установлено в процедуре события MyDataControl1_Load страницы с веб-частями, значок заголовка все равно отображается, потому что его значение по умолчанию предоставлено вашей реализацией IWebPart.