Події в windows
Додатки Windows управляються повідомленнями. Це означає, що додаток спілкується з Windows. a Windows - з додатком за допомогою визначених повідомлень. Ці повідомлення є структури, що містять різні порції інформації, які використовуються додатком і самої Windows для того, щоб визначити, що потрібно робити далі. До появи таких бібліотек, як MFC. і таких середовищ розробки, як VisualBasic. розробнику доводилося самому піклуватися про те, як потрібно обробляти приходять повідомлення. VisualBasic і .NET обгортають деякі з цих вхідних повідомлень в щось, зване подіями. Якщо ваша програма повинна реагувати на специфічне вхідне повідомлення, ви повинні обробити відповідна подія. Загальний приклад цього - коли користувач клацає на кнопці форми. При цьому Windows посилає повідомлення WM_MOUSECLICK оброблювачу подій кнопки (іноді званого віконної процедурою, або WndProc). Для розробників .NET це виглядає як подія кнопки OnClick.
При розробці об'єктно-орієнтованих додатків потрібна інша форма взаємодії об'єктів. Коли в одному з ваших об'єктів відбувається щось цікаве, то, ймовірно, інші об'єкти повинні бути поінформовані про це. І знову на допомогу приходять події. Точно так же, як .NETFramework обгортає повідомлення Windows в події, ваші додатки можуть використовувати події в якості комунікаційних посередників між об'єктами.
Делегати застосовуються як засіб формування подій при отриманні додатком повідомлень.
Одним з переваг дизайну подій в С # є те, що для їх використання зовсім не обов'язково що-небудь знати про що лежить в їх основі механізм делегування. Тому ми почнемо цей розділ з короткою дискусії про події з точки зору клієнтського програмного забезпечення. Ми зосередимося на тому, як слід писати код, щоб отримати повідомлення про події, не надто турбуючись про те, що відбувається «за лаштунками» - просто для того, щоб продемонструвати, наскільки проста насправді робота з подіями. Після цього ми напишемо приклад, що генерує події, і, зробивши це, побачимо, як працює зв'язок між подіями і делегатами.
В даному контексті термін «подія» використовується в двох різних сенсах. По-перше, як деякий цікавить нас подія, а по-друге - як строго певний об'єкт на мові С # - об'єкт, який обслуговує процес повідомлення. Використовуючи цей термін далі, ми будемо говорити про нього або як про подію С #, або, коли сенс очевидний з контексту, - як просто про подію.
Подання події з точки зору одержувача
Тепер десь всередині одержувача буде метод, який відповідає за обробку події. Цей оброблювач подій буде запускатися щоразу, коли виникає зареєстроване для нього подія. І тут вступають в дію делегати. Оскільки відправник не має жодного уявлення про одержувача (одержувачів), між ними не може бути ніяких посилань. В якості посередника використовуються делегати. Відправник визначає делегат, який буде використаний одержувачем. Одержувач, реєструє обробник події. Процес прикріплення обробника до події називається прив'язкою події. Простий приклад прив'язки події Click допоможе нам проілюструвати цей процес.
btnOne.Click + = new EventHandler (Button_Click);
При цьому відбувається ось що: ми повідомляємо виконуючої системі, що коли виникає подія Click для кнопки btnOne. то повинен бути виконаний метод Button_Click. EventHandler - це делегат, який використовує подія для призначення обробника (Button_Click) події (Click). Відзначимо, що ми використовували операцію + = для додавання методу до списку делегатів. Все це означає, що події можна призначити більше одного обробника. Оскільки це груповий делегат, до нього застосовні всі правила про додавання множинних методів; однак немає ніякої гарантії того, в якому порядку вони будуть викликані. Продовжимо далі, перетягнувши в форму ще одну кнопку, і перейменуємо її в btnTwo. Тепер зв'яжемо подія Click кнопки btnTwo з тим же методом Button_Click. як показано нижче:
btnOne.Click + = new EventHandler (Button_Click);
btnTwo. Click + = new EventHandler (Button_Click);
Делегат EventHandler визначено середовищем .NETFramework. Він знаходиться в просторі імен System. і всі події, певні в .NETFramework. використовують його. Як уже згадувалося вище, список делегатів повинен мати одну і ту ж сигнатуру. Очевидно, що це так само справедливо і для делегатів подій. Нижче показано визначення методу Button_Click:
private void btnOne_Click (object sender, EventArgs e)
Другий параметр - EventArgs - це об'єкт, що містить іншу потенційно корисну інформацію про подію. Цей параметр може бути будь-якого типу, успадкованого від EventArgs.
Так, подія MouseDown використовує MouseDownEventArgs. Він містить такі властивості, як кнопка миші, яка була натиснута, координати X і Y покажчика, а також іншу інформацію, пов'язану з подією. Зверніть увагу на шаблон імені, що закінчується на EventArgs. Пізніше ми побачимо, як створювати і застосовувати для користувача об'єкт на базі EventArgs.
Також варто звернути увагу на ім'я методу. За встановленим угодою будь-обробник подій повинен дотримуватися стилю «іменування об'ект_собитіе».
Тут об'єкт - це об'єкт, що збуджує подія, а подія - сама подія. Це всього лише угода, але для гарної Новомосковскбельності коду його слід дотримуватися.
Останнє, що потрібно зробити в цьому прикладі - додати деякий код, який насправді зробить щось корисне в обробнику. Згадаймо, що у нас дві нопкі використовують один і той же обробник. Тобто перше, що потрібно зробити - визначити, яка з них згенерувала подія, а потім виконати відповідну дію. В даному прикладі ми просто виведемо певний текст на мітку форми. Для цього перетягнемо з панелі інструментів на форму елемент управління типу мітки і назвемо її lblInfо. Потім напишемо наступний код в методі Button_Click:
if (((Button) sender) .Name == "btnOne")
lblInfo.Text = "Натиснуто перша кнопка";
lblInfo.Text = "Натиснуто друга кнопка";
Відзначимо, що оскільки параметр sender відправлений як об'єкт, його потрібно Пристая до типу об'єкта, що викликав подія, в даному випадку - до Button. У цьому прикладі ми використовуємо властивість Name для визначення кнопки, що викликала подія. Однак ви можете використовувати інші властивості. Зручно використовувати в цьому сценарії властивість Tag. оскільки воно може зберігати все, що ви побажаєте в нього помістити. Щоб побачити, як працюють групові можливості делегата, додамо ще один метод до події Click кнопки bthTwo. Використовуємо ім'я методу за замовчуванням. Тіло конструктора форми тепер буде виглядати приблизно так:
this.btnOne.Click + = new System.EventHandler (this.btnOne_Click);
this.btnTwo.Click + = new System.EventHandler (this.btnOne_Click);
this.btnTwo.Click + = new System.EventHandler (this.btnTwo_Click);
Якщо ми дозволимо VisualStudio самостійно створити заготовку, то побачимо наступний метод-в кінці вихідного файлу. Однак виклик функції MessageBox потрібно додати вручну:
private void btnTwo_Click (object sender, EventArgs e)
MessageBox.Show ( "Це сталося тільки при подію клацання на кнопці 2");
Якщо повернутися назад і використовувати анонімні методи, то методи Button_Click і btnTwo_Click не знадобляться.
При запуску цього прикладу клацання на кнопці btnOne змінить текст мітки. Луг на кнопці btnTwo не тільки змінить текст мітки, але також відобразить MessageBox (вікно повідомлення). Нагадаємо ще раз, що немає ніяких гарантій того, що зміни тексту мітки відбудеться до появи MessageBox. тому не пишіть залежний код в обробниках.
Може здатися, що для того, щоб у всьому цьому розібратися, необхідно вивчити безліч концепцій, але на практиці обсяг кодування, яке потрібно виконати в приймальнику, дуже невеликий. Також слід мати на увазі, що писати приймачі подій вам доведеться набагато частіше, ніж їх відправники. По крайней мере, що стосується користувальницького інтерфейсу Windows. Microsoft вже розробила всі необхідні відправники подій, які вам знадобляться (вони закодовані в базових класах .NET. В просторі імен Windows.Forms).