Динамическое управление обработчиками 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Динамическое управление обработчиками



Вы составили себе представление о том, как операция += связала событие с обработчиком. И тут возникает несколько логичных вопросов:

Вопрос 1: Перед тем как оператор

b1.Click += ButtonClick;

связал с щелчком по кнопке b1 обработчик ButtonClick, был ли список обработчиков пуст?

Ответ 1: Нет. Уже для стандартного класса Form определены обработчики щелчка по кнопкам. Это можно заметить и визуально – щелчки по кнопкам приводят к эффекту «вдавливания» кнопки. Вопрос, который пока останется без ответа – где находятся эти обработчики?

Вопрос 2: Можно ли связать с событием несколько обработчиков и что при этом происходит?

Ответ 2: Связать несколько обработчиков можно путем многократного выполнения оперции +=. В этом случае все обработчики срабатывают последовательно в том порядке, в котором они добавлялись в множество обработчиков события.

Вопрос 3: Можно ли выполнить обратную операцию – исключить обработчик из списка?

Ответ 3: Да, это делается с помощью аналогичной операции -=.

Попробуем продемонстрировать это на примере. Рассмотрим, как работает программа, содержащая следующий класс MainWindow:

class MainWindow:Form

{

...

public MainWindow()

{

...

b1.Click += ButtonClick;

b1.Click += NewButtonClick;

...

b2.Click += ButtonClick;

b2.Click += NewButtonClick;

...

}

private void ButtonClick(object sender, EventArgs ea)

{ ((Button)sender).Text = DateTime.Now.ToString(); }

  private void NewButtonClick(object sender, EventArgs ea)

{ this.Text=((Button)sender).Text;

if (sender == b1)

b2.Click -= NewButtonClick;

else

  b1.Click -= NewButtonClick;

}

}

Первоначально (после создания формы) обе кнопки реагируют на щелчок двумя обработчиками:

- первый обработчик выводит на кнопку дату и время;

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

Допустим, сначала пользователь щелкнул по первой кнопке. Тогда условный оператор во втором обработчике исключит этот обработчик из списка обработчиков щелчка второй кнопки. Таким образом, «победила» первая кнопка – теперь только она выводит дату и время и на своей поверхности и в заголовке формы.

Аналогично «победит» вторая кнопка, если пользователь щелкнет сначала по ней.

Элемент управления Timer

Модель выполнения оконного приложения существенно ориентирована на события. Можно говорить, что оконное приложение функционирует только в ответ на происходящие с ним (его элементами) события. Отсюда можно сделать вывод – если пользователь не дотрагивается до «органов управления» компьютером, программа бездействует в ожидании новых событий. Это означало бы, что мы не можем реализовать большое количество задач, которые демонстрируют автономную, независимую от пользователя динамику.

В качестве простого примера рассмотрим решение следующей задачи. В окне приложения находится небольшая квадратная кнопка, которая каждую секунду перемещается в случайное место, оставаясь целиком в пределах окна. Пользователь пытается успеть щелкнуть по поверхности кнопки. Если ему это удается сделать 3 раза, кнопка перестает двигаться.

Для решения этой задачи нужно обеспечить перемещение кнопки независимо от каких-либо действий пользователя. Тем не менее, это перемещение может быть только результатом реакции на некоторое событие. Для разрешения сложившегося противоречия нам нужно событие, которое будет происходить без участия пользователя, и связано с течением времени. Специально для таких задач предусмотрен элемент управления Timer, очень напоминающий обычный будильник. Таймер умеет порождать через указанный интервал времени сигнал – событие Tick. Интервал времени определяется свойством Interval, измеряемым в миллисекундах (1 сек = 1000 миллисекунд). Элемент Timer имеет логическое свойство Enabled: true означает, что Timer включен и генерирует событие Tick, false – Timer выключен. И последнее замечание – Timer не является визуальным элементом. Как следствие, его не нужно помещать в коллекцию Controls объекта-формы.

Далее приведем код класса формы, решающий нашу задачу:

class MyForm:Form

{ private Button target; //кнопка-цель

private Timer timer;   

private const int TSize = 50; //размер кнопки

private int lifes; //количество "жизней" кнопки

public MyForm()

{ lifes = 3;

target = new Button();

Jump();

target.Click += TargetClick;

this.Controls.Add(target);

 

timer = new Timer();

timer.Interval = 1000;

timer.Tick += TimerTick;

timer.Enabled = true;

}

private void TimerTick(object sender, EventArgs ea)

{

Jump();

}

private void TargetClick(object sender, EventArgs ea)

{

lifes--;

if (lifes <=0)

timer.Tick -= TimerTick;

 // или timer.Enabled = false;

}

  private void Jump()

{

Random r = new Random();

int Left=r.Next(0,this.ClientSize.Width-TSize);

int Top=r.Next(0,this.ClientSize.Height-TSize);

target.Bounds = new Rectangle(Left, Top, TSize, TSize);

}

}

Комментарии

Элемент управления ListBox

Часто возникает необходимость отображать в окне большое множество информационных элементов на сравнительно небольшом пространстве. Для этого хорошо подходят списки с вертикальными линейками прокрутки. Такие элементы создаются как объекты класса ListBox. Класс ListBox сочетает в себе свойства визуального элемента и знакомого Вам контейнерного класса ArrayList.

Для демонстрации возможностей этого элемента создайте оконное приложение, в окне которого располагаются кнопка button1 и список listBox1.

Для управления обычными визуальными свойствами у класса ListBox имеются уже знакомые свойства – Height, Width, Top, Left и т.д. Для доступа к «контейнерным» функциям следует использовать свойство Items. Items представляет все множество элементов, находящихся в списке. Возможности этой коллекции сходны с возможностями ArrayList. В первую очередь это означает, что в список с помощью метода Add можно добавлять элементы любых типов.

Например, для добавления в список целого числа 1 можно выполнить оператор listBox1.Items.Add(1).

Следующий обработчик щелчка по кнопке добавляет в список разные объекты:

private void button1_Click(object sender, EventArgs e)

{

Random r=new Random();

switch (r.Next(1, 5))

{ case 1: listBox1.Items.Add(1); break;

case 2: listBox1.Items.Add('a'); break;

case 3: listBox1.Items.Add("Hi"); break;

case 4: listBox1.Items.Add(new Random()); break;

}

}

Все элементы успешно отображаются в списке. Даже объект-генератор случайных чисел:

Объекты любых типов (классов) отображаются в списке с помощью метода ToString своего класса. Если в классе нет собственного метода ToString, действует унаследованный метод – обычно это метод ToString из класса Object, который возвращает строку с полным именем класса.

В списке объекты хранятся в первоначальном виде: значимые типы непосредственно копируются в список, а для ссылочных в список помещается только ссылка на объект.

Метод Add добавляет элементы в конец списка.

Для программного доступа к выбранному в списке элементу используются свойства SelectedIndex (номер выбранного элемента) и SelectedItem(сам выбранный элемент, это свойство имеет тип Object).

Добавьте на форму еще одну кнопку (button2). Сделаем так, чтобы в результате щелчка по кнопке, в заголовке формы отображался выбранный элемент. Для этого напишем следующий обработчик:

private void button2_Click(object sender, EventArgs e)

{ if (listBox1.SelectedIndex!= -1)

Text = Convert.ToString(listBox1.SelectedItem);

else

Text = "Элемент не выбран";

}

Здесь учтена ситуация, когда в списке ничего не выбрано. В этом случае свойство SelectedIndex равно -1.

Наконец, для взаимодействия с пользователем элемент ListBox обычно использует событие SelectedIndexChanged. Это событие происходит в любом случае изменения номера выбранного элемента:

- в случае выбора пользователем элемента списка мышью;

- в случае выбора пользователем элемента списка клавиатурой;

- изменение значения свойства SelectedIndex программным путем.

Рассмотрим следующий пример обработчика этого события:

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)

{ if ((listBox1.SelectedIndex < 5) &&

(listBox1.SelectedIndex < listBox1.Items.Count-1))

listBox1.SelectedIndex++;

}

Если пользователь выбирает мышью некоторый элемент в списке, возникает первое событие SelectedIndexChanged. Далее при выполнении условия оператора if осуществляется программное увеличение свойства SelectedIndex. Это в свою очередь приводит к возникновению второго события SelectedIndexChanged, его обработке и т.д. Этот процесс останавливается благодаря условию if либо на пятом элементе списка, либо в конце списка.

Далее приводятся другие популярные средства управления коллекцией Items:

public int Count

Свойство, позволяющее узнать количество элементов в коллекции

public void AddRange (Object[] items)

Добавление в коллекцию массива объектов

public void AddRange (ObjectCollection value)

Добавление в коллекцию содержимого другого списка

public virtual void Clear ()

Очистка содержимого коллекции

public bool Contains (Object value)

Определяет, найден ли данный объект в коллекции

public int IndexOf (Object value)

Определяет позицию данного элемента в коллекции (-1, если не найден)

public void Insert (int index,Object item)

Добавляет данный объект в коллекцию в указанную позицию

public void Remove (Object value)

Удаляет данный элемент из коллекции

public void RemoveAt (int index)

Удаляет из коллекции объект в указанной позиции

Этот перечень еще раз подтверждает сходство коллекции Items с объектами ArrayList. Естественно, коллекцию Items можно индексировать.



Поделиться:


Последнее изменение этой страницы: 2021-12-15; просмотров: 42; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.135.194.15 (0.022 с.)