Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: event EventHandler EventHandlerList  (Прочитано 6415 раз)
0 Пользователей и 1 Гость смотрят эту тему.
bwwebm
Гость
« : 29-04-2009 10:33 » 

Добрый день.
Столкнулся со следующей проблемой, которую попробую описать на примере.

Допустим что существует button1 которой было назначено событие Click += button1_Click(...) через студию.
Функция button1_Click - предположим выводит сообщение MessageBox("Hello");
Далее я размещаю еще одну кнопку на форме,  button2 ей назначаю событие Click += button2_Click(...)

А тут как раз и проблема, в обработчике button2_Click() делаю примерно следующее:

private void button2_Click(object sender, EventArgs e) {
            Button btn = new Button();
            btn.Parent = (sender as Control).Parent;
            btn.Left = 10;
            btn.Top = 20;
            btn.Text = "Hello";
            //Тут мне требуется назначить обработчик события Click такой же как у (например) sender
            //хотя это может быть и любой другой компонент
            //конечно я могу сделать так:
            btn.Click += new EventHandler(button1_Click);
            //но это не является решением задачи
            //Пробую сделать как-то так:
            System.Reflection.EventInfo einfo = sender.GetType().GetEvent("Click");
            einfo.AddEventHandler(btn, /*что у нас тут?*/);
}

Теперь собственно главное:
 что у нас тут?:
   я вставлял сюда new EventHandler(button1_Click) и работает как надо - но по условиям моей задачи я незнаю: не кол-ва, не названий функций обработчиков

Тоесть мне надо узнать, какие обработчики назначены Control a событие Click и назначить их Control b событию Click

Что то вроде следующего, но я ничего подобного найти не смог:

System.Reflection.EventInfo einfo = a.GetType().GetEvent("Click");

SomeTypeForHandler[] hndl = a.GetClickHandlers();

foreach(System.Delegate h in hndl) {
   einfo.AddEventHandler(btn, h);
}



Visual Studio 2005
.NET 2.0
C#
Записан
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 29-04-2009 10:53 » 

А можно еще раз объяснить, что именно хочешь сделать и чего этим хочешь добиться (или зачем это надо)?
Записан

ещё один вопрос ...
nikedeforest
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #2 : 29-04-2009 10:58 » 

Как вариант, пробегать по всем контролам, смотреть событие Click и выдергивать от туда методы, если не ошибаюсь свйством Method. И все что на дергал вешать на событие созданной кнопки. Если я конечно правильно понял, что требуется
« Последнее редактирование: 29-04-2009 11:05 от nikedeforest » Записан

ещё один вопрос ...
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 29-04-2009 11:48 » 

1) Не понял, зачем у кнопки Parent'ом объявлять другую кнопку - они же не вложенные.

2) Белые люди делают так: заводят единственный обработчик anyButton_Click и назначают его всем кнопкам. Внутри обработчика через (sender as Button) определяют, какая кнопка сработала, и в зависимости от этого предпринимают те или иные действия. Можно завести хэш-таблицу, где ключами будут кнопки, а значениями - объекты, реализованные по шаблону проектирования "Команда" (Command).

Тот же принцип работает на уровне WinAPI: окно имеет единственную callback-функцию обработки событий, внутри которой через switch определяются типы событий и выполняются разные действия. (Только Framework (как и большинство других библиотек это скрывает от программиста для удобства.) Здесь же в качестве идентификатора события выбирает объект кнопки.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
bwwebm
Гость
« Ответ #4 : 29-04-2009 12:05 » 

Попробую пере объяснить:

Есть некий "шаблонный" компонент (допустим Button) который в редакторе размещен на форме и ему назначено событие Click по которому на экран выводится сообщение (да что угодно).
Далее в некий момент времени, (предположим что при нажатии на другой Button) в режиме Runtime создается компонент, предположим что это будет новый TabPage для существующего TabControl или это будет снова Button, но подразумевается что наличие эвента Click гарантированно (т.е. на это не надо отвлекаться).
Теперь после создания, необходимо событию созданного компонента Click присвоить абсолютно теже делегаты что и были назначены в редакторе для Button в самом начале. Важно еще то, что во время работы Button на событие Click может добавить или лишиться делегатов.
И так. Мы имеем шаблонную кнопку на форме и только что создали новую кнопку. Теперь нужно новой кнопке присвоить все обработчики события Click эталонной кнопки.



* Делегат - я подразумеваю обработчик события "new EventHandler(void function)"
* Я не назначал Parent новой кнопки старую кнопку. Я наначил им одинаковых Parentов. btn.Parent = (sender as Control).Parent
Записан
bwwebm
Гость
« Ответ #5 : 29-04-2009 12:12 » 

Как вариант, пробегать по всем контролам, смотреть событие Click и выдергивать от туда методы, если не ошибаюсь свйством Method. И все что на дергал вешать на событие созданной кнопки. Если я конечно правильно понял, что требуется
Как вариант, пробегать по всем контролам, смотреть событие Click и выдергивать от туда методы, если не ошибаюсь свйством Method. И все что на дергал вешать на событие созданной кнопки. Если я конечно правильно понял, что требуется

Правильно но, не совсем. Ненадо бегать по всем контролам. Есть контрол "a" - как эталон и есть новый только что созданный "b". Как событию (можно на примере Click) b.Click присвоить a.Click - "b.Click = a.Click"?
Прямое присваивание естественно недопустимо.
Поэтому мне кажется что нужно откуда то вытащить эти делегаты события a.Click
Как вешать делегат я в примере показал, а вот как мне получить СПИСОК этих делегатов!?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #6 : 29-04-2009 12:39 » 

bwwebm, давай ты лучше начнёшь с сути задачи, которую ты решаешь. В сути задачи нет никаких кнопок и табов, а есть что-то нужное пользователю. У меня такое впечатление, что весь подход какой-то нездоровый. Опять же, белые люди сохраняют отдельно экземпляры делегатов (в глобальном списке, например), а потом назначают их разным событиям.

А для Marshal, когда делегат преобразуется в указатель на функцию, сохранение делегата в отдельной переменной вовсе обязательно, иначе его уберёт сборщик мусора, и программа упадёт.
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
bwwebm
Гость
« Ответ #7 : 29-04-2009 12:57 » 

Суть объяснять долго, прийдется писать много лишнего не относящегося к конкретному решению, попробую еще конкретизировать.

Вопрос: как назначить обработчики произвольного события произвольного компонента новому компоненту того же типа. Или можно сказать, что мне нужно клонировать события (Events) существующего компонента в новый (который создается в runtime).

Например, на форме есть 2 кнопки и 3 чекбокса. Если обратиться к коллекции this.Controls то мы получим коллекцию из 5 элементов (чилдов главной формы). А теперь попробуйте создать их копии и тоже разместить на форме. Что касается визуальных свойств, то с этим у меня не возникает проблем, установить их одинаковыми, но как скопировать события?
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #8 : 30-04-2009 13:10 » 

Код: (Text) C# 1.1
using System;

namespace TestDelegate
{
        delegate void EventDelegate(int eventContainerID);

        class EventContainer
        {
                private int id;

                public EventContainer(int id)
                {
                        this.id = id;
                }

                public event EventDelegate Event;

                public void Action()
                {
                        this.OnEvent();
                }

                protected void OnEvent()
                {
                        if(this.Event != null)
                        {
                                this.Event(this.id);
                        }
                }

                public EventDelegate GetEventDelegate()
                {
                        return this.Event;
                }
        }

        class Program
        {
                static EventContainer eventContainer1, eventContainer2;

                static void ActionTest(int testNo)
                {
                        Console.WriteLine("Test No: {0}", testNo);
                        Console.WriteLine("First container action begin.");
                        eventContainer1.Action();
                        Console.WriteLine("First container action end.");
                        Console.WriteLine("Second container action begin.");
                        eventContainer2.Action();
                        Console.WriteLine("Second container action end.");
                        Console.WriteLine();
                }

                static void EventContainer_Event_FirstVariant(int eventContainerID)
                {
                        Console.WriteLine("Handler type A: container ID is {0}", eventContainerID);
                }

                static void EventContainer_Event_SecondVariant(int eventContainerID)
                {
                        Console.WriteLine("Handler type B: container ID is {0}", eventContainerID);
                }

                static void Main()
                {
                        eventContainer1 = new EventContainer(1);
                        eventContainer2 = new EventContainer(1);

                        eventContainer1.Event += new EventDelegate(EventContainer_Event_FirstVariant);
                        eventContainer1.Event += new EventDelegate(EventContainer_Event_FirstVariant);
                        eventContainer1.Event += new EventDelegate(EventContainer_Event_SecondVariant);
                        ActionTest(1);
                       
                        eventContainer2.Event += eventContainer1.GetEventDelegate();
                        ActionTest(2);

                        Console.ReadLine();
                }
        }
}

Фича event'ов в том, что вне класса, где они объявлены, у них открытыми являются лишь операции add и remove. Доступ к delegate, на котором основан event, возможен только изнутри класса. Если изнутри объекта вернуть делегат (см. метод GetEventDelegate), то его можно добавить к событию другого объекта.

Всё это, мягко говоря, не здорово, извращённый подход какой-то.

bwwebm, ты суть всё же объясни. Обычно за словами "долго объяснять" скрывается непонимание задачи, и такой подход сводится к анекдоту "некогда думать, прыгать надо".

Для меня подобные хакерские подходы "лошадью" оправданы лишь в случае сопровождения старой системы, которую перепроектировать во много раз затратнее, чем хакнуть.
« Последнее редактирование: 30-04-2009 13:19 от dimka » Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines