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 – единственный в своем роде продукт, позволяющий автоматизировать работу над созданием...
Август 2024 (1)
Май 2024 (1)
Апрель 2024 (1)
Октябрь 2018 (14)
Февраль 2017 (3)
Январь 2017 (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

Друзья сайта



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

Оноре де Бальзак:

"Тот, кто ищет миллионы, весьма редко их находит, но зато тот, кто не ищет, не находит их никогда."

Опрос

Какой браузер Вы используете?

Internet Explorer
Google Chrome
Mozilla Firefox
Netscape Navigator
Maxthon Browser
Opera
Mozilla Suite
SeaMonkey
K-Meleon
Safari
Amaya
Avant Browser
SlimBrowser
Другой...