VB.NET вызывает обработчики событий по ссылке
Исходя из Deplhi, я привык вызывать обработчики событий напрямую из экземпляра, используя простой
Button.OnMouseOver([arguments])
Сейчас я нахожусь в VB.NET и не могу найти способ запустить обработчики события без его фактического запуска.
Небольшое объяснение того, что я делаю здесь: при создании новой формы я анализирую ее содержимое, чтобы установить все цвета в соответствии с переменной. В зависимости от того, включена кнопка или нет, она имеет разные цвета, но если кнопка отключена в момент создания, ей все равно нужно пройти через обработчик, чтобы исправить ее цвет.
Это то, что я использую
AddHandler ButtonInstance.EnabledChanged, AddressOf Button_EnabledChanged
Button_EnabledChanged(ButtonInstance, New EventArgs)
Это работает правильно, все же я хотел бы иметь возможность вызывать этот метод непосредственно из объекта, который он обрабатывает, просто потому, что я не всегда заранее знаю имя обработчика события.
Я продолжаю указывать на RaiseEvent, но он, кажется, не делает то, что мне нужно.
Есть ли способ получить обработчик события или запустить его без фактического вмешательства в экземпляр?
2 ответа
Простой ответ - нет. Я уверен, что технически возможно, используя рефлексию, получить список делегатов, которые были добавлены к событию, и вызвать каждого из них, но это был бы уродливый хак, который должен использоваться только в самых отчаянных обстоятельствах. Если вам нужно сделать это, лучший способ в VB.NET - это установить один обработчик события, который всегда вызывается при возникновении события (чтобы вы тоже могли напрямую вызывать его), и который затем содержит список делегатов. который он затем вызывает по очереди. Другими словами, используйте делегатов для создания собственного механизма, похожего на событие, который обеспечивает необходимую вам гибкость. Например, что-то вроде этого:
Private _clickActions As New List(Of Action)()
Public Sub AddClickAction(action As Action)
_clickActions.Add(action)
End Sub
Public Sub PerformClickActions()
For Each action As Action in _clickActions
action?.Invoke()
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs)
PerformClickActions()
End Sub
Если вам нужно сделать это в нескольких местах, с разными видами событий, кажется, что было бы довольно легко создать общий универсальный класс для такого рода вещей.
Какой смысл вызывать обработчики событий без запуска самого события?
Если вы определили событие в своем коде, вы можете запустить его с RaiseEvent EventName
, но это не тот случай EnabledChanged
потому что это определено в базовом классе. Вы также можете добавить суффикс Event к его имени для работы с его обработчиками и т. Д. EventNameEvent.GetInvocationList
Если ваше событие объявлено в базовом классе, который вы не можете изменить, вы можете наследовать этот класс и вызывать методы OnEventName, которые должны инициировать событие и вызвать всех обработчиков. Реальная реализация метода OnEventName может предотвратить запуск события. Это зависит от реализации базового класса.
Поиск и запуск обработчиков событий унаследованного события вручную потребует отражения.