Создание веб-частей

161

Теперь, когда известно, какие шаги необходимо выполнить для создания страниц веб-частей в 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:

Важные свойства класса 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:

Члены интерфейса 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 в качестве изображения заголовка:

Настраиваемая часть элемента управления, реализующего IWebPart

Хотя свойство TitleImageUrl не было установлено в процедуре события MyDataControl1_Load страницы с веб-частями, значок заголовка все равно отображается, потому что его значение по умолчанию предоставлено вашей реализацией IWebPart.

Пройди тесты
Лучший чат для C# программистов