WebClub - Всероссийский Клуб Веб-разработчиков
WebClub.RU » Советы » Управление WEB-формой из пользовательского компонента

Управление WEB-формой из пользовательского компонента


Дата публикации: 13-03-2008

Ivanov_SV

Многократное использование единожды написанного и отлаженного кода - одна из важнейших задач, решение которой в той или иной мере обеспечивают практически все современные системы программирования. Не исключение здесь и технологии ASP.Net, предоставляющие разработчику возможность не только использовать поставляемые в стандартной комплектации WEB-компоненты, но и создавать свои собственные.

В распоряжении разработчика ASP.Net имеются две технологии компонентного программирования: "заказные" компоненты (Web Custom Controls) и пользовательские компоненты (Web User Controls). В документации достаточно подробно описаны преимущества и недостатки тех и других. Стоит отметить, что по некоторым позициям пользовательские компоненты уступают "заказным" компонентам, однако простота их создания во многих случаях позволяет закрыть глаза на мелкие недостатки, а возможность визуальной компоновки делает разработку пользовательских компонентов быстрой и приятной.

Есть, однако, у пользовательских компонентов один недостаток, который может затруднять их полноценное использование в контексте сложных интерактивных форм ввода, - эти компоненты работают практически полностью под управлением исполняющего ядра ASP.Net, что не позволяет работать с ними как с полноценными объектами. В документации описана возможность управления компонентом из страницы, но это управление одностороннее. Термин "одностороннее управление" в данном контексте означает, что инициатором каких-либо действий выступает WEB-форма, на которой установлен компонент, т.е. только из методов формы можно установить значения свойств компонента и/или вызвать какие-либо его целевые методы, но никак не наоборот.

Формально класс System.UI.WebControls.Control, от которого наследуются пользовательские компоненты, имеет свойство Page, которое можно было бы использовать для доступа к странице-владельцу, например, так:

HttpRequest request = Page.Request;

Только вот много ли пользы от доступа к стандартным свойствам и методам страницы? Гораздо важнее было бы иметь возможность вызвать какие-либо специализированные методы страницы, на которой установлен компонент, например, изменить доступность элементов управления или выполнить комплексную проверку данных. Но здесь возникает противоречие - компонент, который (как минимум потенциально) может использоваться на разных страницах, не может знать о том, какие конкретно страницы его будут использовать. (Извечная проблема: что первично - курица или яйцо?) То есть при добавлении в приложение новой формы, на которой мы хотим использовать компонент, придется переписывать сам компонент?!..

Для того чтобы тоньше прочувствовать проблему, представим себе какую-нибудь практическую ситуацию, где может потребоваться управление формой "от компонента".

Пусть требуется сделать форму, в которую вводится ФИО работника. После ввода ФИО пользователь может нажать кнопку поиска - в результате на сервере будет запущен поиск в базе данных. Результатом поиска может быть:

  • 0 записей - работник в базе не найден;

  • 1 запись - работник в базе найден;

  • несколько записей - найдено несколько человек, например, однофамильцы.

В зависимости от результата поиска:

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

  2. работник в базе найден - на форме нужно отобразить компонент для вывода детальной информации о человеке;

  3. найдено несколько человек - на форме нужно отобразить компонент для выбора конкретного человека.

В первом и третьем варианте потребуются некоторые дополнительные действия со стороны пользователя и системы (добавление в БД или идентификация), в случае их успешного завершения форма автоматически должна перейти в состояние 2.

Примечание: этот пример представляет собой фрагмент функциональности формы оформления приказов в системе учета персонала.

Ключевой момент здесь - некоторые компоненты должны выполнить на сервере какие-то действия, и затем содержащая их страница должна перекомпоноваться.

Итак, возможные решения:

  • наследовать форму-владельца не от System.UI.WebControls.Page, а от своего класса;

  • определить интерфейсы взаимодействия главной страницы со своими компонентами и, соответственно, реализовать их в форме-владельце;

  • использовать делегаты, подключаемые к компоненту в форме-владельце;

  • генерировать в компонентах специальные события, а в форме-владельце подключать соответствующие обработчики.

В коде это выглядит примерно так:

Наследование формы от своего класса

public abstract class BasePage : System.UI.WebControls.Page { public virtual abstract void DoSearchModuleAction(int recordCount); } public class MyPage : BasePage { public override void DoSearchModuleAction(int recordCount) { // здесь выполняется реальная работа } } public class SeachModule : System.UI.WebControls.Control { private void Button1_Click() { if (Page is BasePage) ((BasePage) Page).DoSearchModuleAction(Search()); } private int Search() { return 0; } }

Этот вариант имеет следующие недостатки:

  • если потребуется, чтобы некоторая форма содержала компонент, но не предоставляла ему "обратной связи", в классе этой формы все равно придется прописывать все методы управления, хотя бы и пустые;

  • если в ходе разработки появится новый компонент, придется переписывать базовый класс и, соответственно, ВСЕХ его наследников;

  • невозможно разместить компонент в компоненте, т.к. компонент-владелец наследуется от System.UI.WebControls.Control, а не от System.UI.WebControls.Page и, соответственно, не может быть наследован от BasePage.

Определение целевых интерфейсов

Выше в качестве примера был приведен код, иллюстрирующий вызов метода DoSearchModuleAction страницы-владельца из обработчика нажатия кнопки в компоненте SeachModule. Ключевая строка:

if (Page is BasePage) ...

Оператор is выполняет проверку того, что Page является экземпляром класса BasePage (или его наследником), или - ВНИМАНИЕ - что объект Page реализует интерфейс BasePage. Естественным образом напрашивается решение использовать не наследование, а реализацию интерфейсов:

public interface IBasePage { void DoSearchModuleAction(int recordCount); } public class MyPage : System.UI.WebControls.Page, IbasePage { public void IBasePage.DoSearchModuleAction(int recordCount) { // здесь выполняется реальная работа } } public class SeachModule : System.UI.WebControls.Control { private void Button1_Click() { if (Page is IBasePage) ((IBasePage) Page).DoSearchModuleAction(Search()); } private int Search() { return 0; } }

Этот вариант визуально не очень отличается от варианта наследования, но за счет использования интерфейсов достигается главная цель - с одной стороны, компонент не обязан ориентироваться на конкретную форму, а может быть установлен в любой контейнер, будь то форма или другой компонент, и, с другой стороны, обеспечивает достаточно простой способ взаимодействия с формой-владельцем.

Тем не менее, и в этом варианте можно найти некоторые недостатки:

  • т.к. используемая техника не соответствует стандартным схемам, необходимо подробно документировать назначение интерфейсов и их методов;

  • интерфейсы должны быть реализованы только в классе формы (или соответствующего контейнера), что при наличии сложной логики обработки не всегда бывает удобно.

Популярное

Не так давно в сети появился новый сервис, под названием Dead Man Zero. Этот сервис сделал...
Рынок социальных площадок уже давно стал стабильным. Несмотря на то, что время от времени...
Artisteer 4 – единственный в своем роде продукт, позволяющий автоматизировать работу над созданием...
Октябрь 2018 (14)
Февраль 2017 (3)
Январь 2017 (1)
Август 2016 (1)
Май 2016 (2)
Ноябрь 2015 (1)

Карта сайта: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41

Друзья сайта



Случайная цитата

Alan J. Perlis:

"FORTRAN — это не цветок, а сорняк: он вынослив, иногда расцветает и произрастает в каждом компьютере."

Опрос

Ваша ОС?

Windows XP
Windows 7
др. версия Windows
Linux
др. ОС