Управління WEB-формою з компонента користувача
Обговорити на форумі
| Управління WEB-формою з компонента користувача |
| Розглядається можливість керування вмістом WEB-форми з компонента користувача (Web User Control). |
| Багаторазове використання одного разу написаного та налагодженого коду - одне з найважливіших завдань, вирішення якої тією чи іншою мірою забезпечують практично всі сучасні системи програмування. Не виняток тут і технології ASP.Net, що надають розробнику можливість не тільки використовувати WEB-компоненти, що поставляються в стандартній комплектації, але й створювати свої власні. |
У розпорядженні розробника ASP.Net є дві технології компонентного програмування: "замовні" компоненти (Web Custom Controls) та компоненти користувача (Web User Controls). У документації досить докладно описані переваги та недоліки тих та інших. Варто зазначити, що за деякими позиціями користувальницькі компоненти поступаються "замовним" компонентам, проте простота їх створення в багатьох випадках дозволяє заплющити очі на дрібні недоліки, а можливість візуального компонування робить розробку компонентів користувача швидкою і приємною.
Є, однак, у компонентів користувача один недолік, який може ускладнювати їх повноцінне використання в контексті складних інтерактивних форм введення, - ці компоненти працюють практично повністю під управлінням виконуючого ядра ASP.Net, що не дозволяє працювати з ними як з повноцінними об'єктами. У документації описано можливість керування компонентом зі сторінки, але це керування одностороннє. Термін "одностороннє управління" в даному контексті означає, що ініціатором будь-яких дій виступає WEB-форма, на якій встановленокомпонент, тобто. тільки з методів форми можна встановити значення властивостей компонента та/або викликати будь-які його цільові методи, але не навпаки.
Формально класSystem.UI.WebControls.Control, від якого успадковуються компоненти користувача, має властивість Page, яку можна було б використовувати для доступу до сторінки-власника, наприклад, так:
Тільки ось чи багато користі від доступу до стандартних властивостей та методів сторінки? Набагато важливіше було б мати можливість викликати будь-які спеціалізовані методи сторінки, де встановлено компонент, наприклад, змінити доступність елементів управління чи виконати комплексну перевірку даних. Але тут виникає протиріччя - компонент, який (як мінімум потенційно) може використовуватися на різних сторінках, не може знати про те, які сторінки його будуть використовувати. (Одвічна проблема: що первинне - курка чи яйце?) Тобто при додаванні в додаток нової форми, на якій ми хочемо використовувати компонент, доведеться переписувати сам компонент.
Для того щоб тонше відчути проблему, уявімо якусь практичну ситуацію, де може знадобитися управління формою "від компонента".
Нехай потрібно зробити форму, в яку вводиться ПІБ працівника. Після введення ПІБ користувач може натиснути кнопку пошуку – в результаті на сервері буде запущено пошук у базі даних. Результатом пошуку може бути:
Примітка: цей приклад є фрагментом функціональності форми оформлення наказів у системі обліку персоналу.
Ключовий момент тут - деякі компоненти повинні виконати на сервері якісь дії, а потім сторінка, що містить їх, повинна перекомпонуватися.
Отже, можливі рішення:
- наслідуватиформу-власника не відSystem.UI.WebControls.Page, а від свого класу;
- визначити інтерфейси взаємодії головної сторінки зі своїми компонентами та, відповідно, реалізувати їх у формі-власнику;
- використовувати делегати, що підключаються до компонента у формі-власника;
- генерувати у компонентах спеціальні події, а у формі-власника підключати відповідні обробники.
Наслідування форми від свого класу
Цей варіант має такі недоліки:
- якщо потрібно, щоб деяка форма містила компонент, але не надавала йому "зворотного зв'язку", у класі цієї форми все одно доведеться прописувати всі методи управління, хоча б і порожні;
- якщо під час розробки з'явиться новий компонент, доведеться переписувати базовий клас і, відповідно, ВСІХ його спадкоємців;
- неможливо розмістити компонент компоненті, т.к. компонент-власник успадковується відSystem.UI.WebControls.Control, а не відSystem.UI.WebControls.Pageі, відповідно, не може бути успадкований відBasePage>.
Визначення цільових інтерфейсів
Вище в якості прикладу наведено код, що ілюструє виклик методуDoSearchModuleActionсторінки-власника з обробника натискання кнопки в компонентіSeachModule. Ключовий рядок:
Операторisвиконує перевірку того, щоPageє екземпляром класуBasePage(або його спадкоємцем), або - УВАГА - що об'єктPageреалізує інтерфейсBasePage. Природно напрошується рішення використовувати не успадкування, а реалізацію інтерфейсів:
Цей варіант візуально не дуже відрізняється від варіанта спадкування, але за рахунок використанняінтерфейсів досягається головна мета - з одного боку, компонент не повинен орієнтуватися на конкретну форму, а може бути встановлений у будь-який контейнер, чи то форма або інший компонент, і, з іншого боку, забезпечує досить простий спосіб взаємодії з формою-власником.
Тим не менш, і в цьому варіанті можна знайти деякі недоліки:
- т.к. техніка не відповідає стандартним схемам, необхідно докладно документувати призначення інтерфейсів та їх методів;
- інтерфейси мають бути реалізовані тільки в класі форми (або відповідного контейнера), що за наявності складної логіки обробки не завжди зручно.
Використання делегатів
Передати управління формі-власнику можна так:
- як делегат виступає приватний методDoSearchModuleAction; у випадку може використовуватися як метод екземпляра класу форми, а й статичний метод форми і навіть метод іншого класу;
- підключення делегата до компонента виконується у методі Load форми-власника.
Цікава можливість, властива делегатам, – підключати кілька делегатів:
Примітка: Приклад взято з розділу 15.1 специфікації C#.
Генерація подій
Використання обставин мало чим відрізняється від розглянутого вище варіанта, т.к. обробники подій є не що інше, як стандартизовані (за типом значення, що повертається, і набором параметрів) делегати:
Відмінність використання делегатів:
-
обробник події є делегатSearchEventHandler; для обробників подій: тип значення, що повертаєтьсяvo , тому їх використання в більшості випадків повинно бути зрозумілобудь-якого стороннього розробника, що є очевидною перевагою з погляду супроводу або відчуження вихідного тексту.
У деяких випадках, наприклад, якщо програмний продукт розробляється не для відчуження і внутрішні стандарти компанії передбачають відповідні рішення, можна використовувати простіші схеми: делегати та/або інтерфейси.