2015-06-23 2 views
0

Резюме: У VB.NET есть предложение handles для прикрепления обработчиков событий. Когда событие принадлежит производителю DataGridViewColumn, конструктор WinForms удаляет это предложение из кода каждый раз, когда используется диалог «редактировать столбцы» из DataGridView.WinForms: ключевое слово handles исчезает на пользовательском событии DataGridViewColumn

Длинная версия: Я внедрил простой DataGridViewColumn, исходя из класса DataGridViewButtonColumn. Все, что он делает, это добавить событие GetImage, используемое логикой рисования ячейки (код ячейки не имеет отношения к проблеме).

Public Class DataGridViewAdvButtonColumn 
    Inherits DataGridViewButtonColumn 

    Public Sub New() 
     Me.CellTemplate = New DataGridViewAdvButtonCell 
    End Sub 

    Public Event GetImage(ByVal rowIndex As Integer, ByRef image As Image) 

    Friend Sub OnGetImage(ByVal rowIndex As Integer, ByRef image As Image) 
     RaiseEvent GetImage(rowIndex, image) 
    End Sub 

    Public Overrides Function Clone() As Object 
     Return TryCast(MyBase.Clone, DataGridViewAdvButtonColumn) 
    End Function 

End Class 

Теперь предположим, что я использую этот тип колонки на определенной форме, и я прилагаю обработчик к GetImage события, например, так:

Private Sub column_GetImage(rowIndex As Integer, ByRef image As Image) Handles column.GetImage 
    ' ... 
End Sub 

Проблема я испытываю то, что WinForms дизайнер снимает предложение handles всякий раз, когда я открываю диалог «редактировать столбцы» на DataGridView, где размещается столбец. Результат:

Private Sub column_GetImage(rowIndex As Integer, ByRef image As Image) 
    ' ... 
End Sub 

Это, очевидно, не произойдет. Это очень опасно, потому что он в основном остается незамеченным (не создает ошибок компилятора).

Я уже пробовал добавить код к методу Clone столбца, чтобы скопировать связанные обработчики событий. Тем не менее, это ничего не меняло (я заметил, что во время разработки во время разработки нет прикрепленных событий). Я также попытался изменить подпись события на нечто более «обычное» с e As GetImageEventArgs вместо ByRef image As Image; не помогло.

Это должна быть распространенная проблема, но почему-то никто не использует пользовательские события на своем обычном DataGridViewColumns. Так что Google тоже ничего не обнаружил.


Действия для воспроизведения: Чтобы ответить на вопросы пользователя Plutonix, здесь подробные шаги, чтобы воспроизвести это (компилирует с опцией строгой).

  • Создайте проект WinForms.
  • Добавьте DataGridViewAdvButtonColumn класса (код выше) к проекту
  • Добавьте DataGridViewAdvButtonCell класса (код ниже) для проекта
  • Compile
  • Используйте конструктор, чтобы добавить DataGridView в Form1.vb формы.
  • Используйте конструктор, чтобы добавить новый столбец типа DataGridViewAdvButtonColumn в DataGridView
  • Выберите столбец в редакторе свойств, нажмите на иконку события (так, что все события в списке) и дважды щелкните на GetImage события.
  • Вы находитесь в обратном порядке формы с обработчиком событий, как показано в моем примере выше.
  • Вернитесь к дизайнеру; добавьте еще один столбец (тип не имеет значения) к DataGridView
  • Вернитесь к коду. Вы увидите, что оператор handles для обработчика событий, добавленный на предыдущем шаге, теперь исчез. QED

Вот код DataGridViewAdvButtonCell:

Public Class DataGridViewAdvButtonCell 
    Inherits DataGridViewButtonCell 

    Public Overrides Function Clone() As Object 
     Return TryCast(MyBase.Clone, DataGridViewButtonCell) 
    End Function 

    Protected Overrides Sub Paint(graphics As Graphics, clipBounds As Rectangle, cellBounds As Rectangle, 
            rowIndex As Integer, cellState As DataGridViewElementStates, value As Object, formattedValue As Object, 
            errorText As String, cellStyle As DataGridViewCellStyle, advancedBorderStyle As DataGridViewAdvancedBorderStyle, 
            paintParts As DataGridViewPaintParts) 

     MyBase.Paint(graphics, clipBounds, cellBounds, rowIndex, cellState, value, formattedValue, errorText, cellStyle, advancedBorderStyle, paintParts) 

     ' Fire GetImage event 
     Dim image As Image = Nothing 
     DirectCast(OwningColumn, DataGridViewAdvButtonColumn).OnGetImage(rowIndex, image) 
     If image IsNot Nothing Then 
      ' do something.. 
     End If 
    End Sub 

End Class 
+0

'Me.CellTemplate = Новый DataGridViewAdvButtonCell' CellTemplate имеет тип DGVCell, в то время как ваш новый тип является DGVColumn - это привычка компилировать с Option Strict. Я не могу видеть, как ваше новое событие привязано/подключено к событию сотовой живописи. – Plutonix

+0

Кроме того, как этот обработчик событий попал в форму, и колонка в DGV была бы стоит знать. – Plutonix

+0

@Plutonix: для воспроизведения этого не требуется ничего особенного (также он компилируется с опцией strict). Я включил подробный список шагов в вопросе; Я также включил код 'DataGridViewAdvButtonCell'. – Andreas

ответ

0

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

AddHandler column.GetImage, Addressof column_GetImage 
+0

Конечно, но это неудовлетворительно, особенно если этот компонент должен использоваться кем-то другим. – Andreas

+0

Кажется, что ошибка с datagridview edit - вы можете использовать пункт меню «добавить столбцы» в порядке, но любые изменения в редактировании, похоже, перестраивают столбцы, теряя обработчик, прикрепленный таким образом. Если вы снова избегаете конструктора (я знаю, не идеальный), обработчики, которые вы прикрепляете к себе, набрав «handles column1.GetImage», будут оставаться прикрепленными – AaronTheRabbit

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