Нестандартные события классов
Помимо стандартных событий – как реакция программы на действия пользователя, события могут формироваться и внутри Windows-приложений с помощью специальных методов.
События, формируемые самим приложением, позволяют организовать динамическую (во время работы приложения) связь между различными объектами, например, продажа некоторого товара в магазине должно автоматически изменять содержимое многих документов – общий доход от продажи, документ по продаже конкретного товара, наличие этого товара на складе и рекомендации по пополнению товара и т.д.
Таким образом, возникает необходимость информирования некоторых объектов приложения о событии, происшедшем в объекте источнике сообщения.
Механизм взаимодействия источника события с его получателями (иногда их называют клиентами) основан на использовании делегата. В приложении объявляется экземпляр делегата, которому соответствуют стандартные методы обработчиков событий.
Далее необходимо определить класс, являющегося источником события (sender), и в нем метод описывающий событие, и метод инициирующий событие.
В процессе работы приложения объекты обработчиков событий (клиентов), которые хотят получать уведомление об изменении состояния источника, необходимо включить в список методов, обрабатываемых делегатом. Этот процесс называется регистрацией обработчиков событий..
При появлении события все зарегистрированные методы поочередно, с помощью делегата, вызываются на выполнение.
Работу механизма взаимодействия источника события с его получателями рассмотрим на следующем учебном примере.
Задача 14.1 Сформировать массив из 10 случайных целых чисел в диапазоне от минус 5 до 10. Предположим, что отрицательные значения недопустимы и для них мы будем формировать события.Необходимо напечатать массив, вычислить его сумму и нарисовать график изменения значений.
Если значение массива число отрицательное, то необходимо формировать событие, не которое должны реагировать два обработчика. Первый должен поменять знак у отрицательного числа, а второй должен изменить сумму чисел в соответствии с новым значением элемента массива.
Для наглядности предусмотреть вывод графика измененных значений массива.
Итак, для создания и использования события нужно, прежде всего, объявить делегата, с помощью которого реализуется связь между источником события и его клиентами.
В библиотеке .NET описано огромное количество стандартных делегатов, предназначенных для реализации механизма обработки событий. Большинство этих классов оформлено по одним и тем же правилам:
– имя делегата включает название события и заканчивается суффиксом EventHandler;
– делегат имеет два формальных параметра. Первый параметр задает источник события и имеет тип object. Второй параметр задает аргументы события и имеет тип EventArgs или производный от него.
Рекомендуется при объявлении делегата придерживаться этих правил, например:
public delegate voidZamenaEventHandler(object sender, ZamenaEventArgs arge);
В этом примере мы создаем делегата для обработки события Zamena (замена), связанного с изменениями, которые должны произойти в объекте-источнике события. В описании делегата указаны два аргумента: объект sender, создавший событие, и объект arge типа ZamenaEventArgs, содержащий связанные с событием параметры.
Поскольку нам понадобится передавать только индекс массива, то лучше определить класс ZamenaEventArgs следующим образом:
public class ZamenaEventArgs : EventArgs
{
public int item;
}
Следующим этапом в реализации механизма обработки событий является определение класса, являющегося источником события (sender), и в нем метода, инициирующего событие. Этот метод имеет специальный формат записи и во многом определяется форматом записи соответствующего ему делегата – после определения спецификатора доступа к методу (обычно это public) записывается служебное слово event, после которого указывается тип, заданный делегатом, и имя события. Например:
public event ZamenaEventHandler Zamena;
Полное описание класса выглядит следующим образом:
class sobit
{
public event ZamenaEventHandler Zamena;
public void prov(ZamenaEventArgs arge)
{
if (masi[arge.item] < 0)
{
Zamena(this,arge);
}
}
}
На следующем этапе реализации механизма обработки событий необходимо определиться с классами получателями событий. Особенность этих классов является то, что в них должны находиться методы обработчиков событий, формат записи которых должен совпадать с форматом записи соответствующего делегата. Например:
class zam1
{
public void OnZam1(object sender, ZamenaEventArgs e)
{
masi[e.item] = masi[e.item] * (-1);
}
}
Регистрацию обработчиков событий необходимо производить для объектов (не классов) классов обработчиков событий. Это возможно только во время работы приложения – объекты (переменные) создаются во время работы приложения, например, во время инициализации формы:
public Form1()
{
InitializeComponent();
zam1 z1 = new zam1();
zam2 z2 = new zam2();
so.Zamena += z1.OnZam1;
so.Zamena += z2.OnZam2;
}
Для демонстрации работы приложения использованы две кнопки – «Формирование массива» и «Проверка массива и запуск событий».
Исходный код программы имеет следующий вид:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public delegate void ZamenaEventHandler(object sender,
ZamenaEventArgs arge);
public int cob=0;
public static int sum = 0;
public static int[] masi = new int[10];
public class ZamenaEventArgs : EventArgs
{
public int item;
}
class sobit
{
public event ZamenaEventHandler Zamena;
public void prov(ZamenaEventArgs arge)
{
if (masi[arge.item] < 0)
{
Zamena(this,arge);
}
}
}
sobit so = new sobit();
class zam1
{
public void OnZam1(object sender, ZamenaEventArgs e)
{
masi[e.item] = masi[e.item] * (-1);
}
}
class zam2
{
public void OnZam2(object sender, ZamenaEventArgs e)
{
//if(masi[e.item]>0)//Проверка очередности обработки событий
sum = sum + 2 * masi[e.item];
}
}
public Form1()
{
InitializeComponent();
zam1 z1 = new zam1();
zam2 z2 = new zam2();
so.Zamena += z1.OnZam1;
so.Zamena += z2.OnZam2;
}
private void button1_Click(object sender, EventArgs e)
{
cob = 0; sum = 0;
string ss="";
Random rnd = new Random();
for(int i=0;i<10;i++)
{
masi[i] = rnd.Next() % 15 - 5;
sum = sum + masi[i];
ss = ss + masi[i].ToString() + " ";
}
textBox1.AppendText("Исходный массив: \r\n");
textBox1.AppendText(ss + "\r\n");
textBox1.AppendText("Сумма элементов="+sum.ToString()+"\r\n");
this.Invalidate();
}
private void button2_Click(object sender, EventArgs e)
{
cob=1;
ZamenaEventArgs zz = new ZamenaEventArgs();
for (int i = 0; i < 10; i++)
{
zz.item = i;
so.prov(zz);
}
textBox1.AppendText("Сумма элементов="+sum.ToString()+"\r\n");
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawLine(new Pen(Brushes.Blue, 2), 10, 200, 250, 200);
Pen myPen = new Pen(Color.Red, 2);
if (cob == 0)
{
for (int i = 1; i < 10; i++)
g.DrawLine(myPen,i*10,(200-masi[i-1]*10),(i+1)*10,(200-masi[i]*10));
}
if (cob == 1)
{
for (int i = 1; i < 10; i++)
g.DrawLine(myPen,i*10+110,(200-masi[i-1]*10),(i+1)*10+110, (200-masi[i]*10));
}
}
}
}
Работа программы:
Рисунок 14.3 Работа приложения с обработкой событий
Дата добавления: 2018-11-25; просмотров: 233;