0

Я пытаюсь написать умную небольшую функцию здесь, которая добавит указанный делегат в качестве обработчика событий ко всем элементам управления в коллекции для любого динамического события. То, что я пытаюсь сделать, это написать это как полностью общую функцию, чтобы я мог использовать ее в различных проектах (возможно, в том числе и в какой-то библиотеке инструментов).Можно ли динамически указывать тип события при использовании AddHandler?

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

Вот моя «работа в прогрессе» к югу:

Private Sub AddHandlerToControls(controlList As ControlCollection, eventToHandle As EventHandler, eventHandlerDelegate As Func(Of Object, EventArgs), Optional filterList As List(Of Type) = {}) 
    For Each controlInList As Control In controlList 
     If controlInList.HasChildren Then 
      AddHandlerToControls(controlInList.Controls, controlInList.MouseEnter, eventHandlerDelegate, filterList) 
     End If 
     If filterList.Count > 0 Then 
      If filterList.Contains(controlInList.GetType) = False Then 
       Continue For 
      End If 
     End If 
     AddHandler controlInList.MouseEnter, eventHandlerDelegate 
    Next 
End Sub 

В идеале я хотел бы использовать параметр eventToHandle там в конце в AddHandler заявления вместо конкретно с помощью controlInList.MouseEnter. Как это:

AddHandler eventToHandle, eventHandlerDelegate 

Таким образом, я мог бы назвать эту функцию динамически в методе form.load, и называют это вроде как я делал раньше в суб, где она рекурсивно, называющая себя для дочерних элементов управления. Как-то сказать «для этого списка элементов управления я хотел бы использовать этот делегат в качестве обработчика событий« MouseEnter ». Как так:

AddHandlerToControls(Me.Controls, control.MouseEnter, MouseEnterHandlerDelegate, new List(Of Type) {TextBox, ComboBox}) 

Это может быть просто wishfull мышление, я начинаю думать, что это не вполне возможно на этом уровне «родовой», но это достаточно интересная проблема, что я думал, что я должен в наименее спросите.

Edit для решения: предложение

Джона Скита использования Reflection в конечном итоге работает для меня. Вот последняя функция:

Private Shared Sub AddHandlerToControls(controlList As Control.ControlCollection, eventToHandle As String, eventHandlerDelegate As MethodInfo, Optional filterList As List(Of Type) = Nothing) 
    For Each controlInList As Control In controlList 
     If controlInList.HasChildren Then 
      AddHandlerToControls(controlInList.Controls, eventToHandle, eventHandlerDelegate, filterList) 
     End If 
     If Not filterList Is Nothing Then 
      If filterList.Contains(controlInList.GetType) = False Then 
       Continue For 
      End If 
     End If 

     Dim dynamicEventInfo As EventInfo = controlInList.GetType.GetEvent(eventToHandle) 
     Dim handlerType As Type = dynamicEventInfo.EventHandlerType 
     Dim eventDelegate As [Delegate] = [Delegate].CreateDelegate(handlerType, eventHandlerDelegate) 
     dynamicEventInfo.AddEventHandler(controlInList, eventDelegate) 
    Next 
End Sub 

И как я это называю, и делегат используется:

AddHandlerToControls(Controls, "MouseClick", GetType(MainFrm).GetMethod("MouseClickEventDelegate"), New List(Of Type) From {GetType(TextBox), GetType(ComboBox)}) 

Shared Sub MouseClickEventDelegate(sender As Object, eventArgs As EventArgs) 
    sender.SelectAll() 
End Sub 

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

+0

Вы можете попробовать что-то через отражение на линиях этой ссылки: http: // stackoverflow.ком/вопросы/2802774/трассировка-все-события-в-Vb-сеть. Но я думаю, что вы не можете дать вид стандартного лечения, которое вы ищете для всех событий со всех элементов управления. – varocarbas

+0

Ну ... Если Джон Скит говорит, что это возможно, я думаю, что нет никаких сомнений. Если вам не ясно, ответ в приведенной выше ссылке содержит рабочий код VB.NET для второго варианта, который он предлагает. – varocarbas

ответ

4

два варианта:

  • Укажите "подписной делегат" с помощью лямбда-выражения. Я не хотел бы, чтобы догадаться, что это будет выглядеть в VB, но в C# это было бы что-то вроде:

    (control, handler) => control.MouseEnter += handler; 
    

    Тогда вам просто необходимо пройти каждый элемент управления на делегат.

  • Укажите имя события как строку и используйте отражение, чтобы получить событие и подписаться (Type.GetEvent, затем EventInfo.AddEventHandler).

+0

пошел с методом отражения. Я редактировал свое оригинальное сообщение, чтобы включить то, что работало в конце. – Anthony

Смежные вопросы