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 может предотвратить запуск события. Это зависит от реализации базового класса.

Поиск и запуск обработчиков событий унаследованного события вручную потребует отражения.

Другие вопросы по тегам