Резюме: У 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
'Me.CellTemplate = Новый DataGridViewAdvButtonCell' CellTemplate имеет тип DGVCell, в то время как ваш новый тип является DGVColumn - это привычка компилировать с Option Strict. Я не могу видеть, как ваше новое событие привязано/подключено к событию сотовой живописи. – Plutonix
Кроме того, как этот обработчик событий попал в форму, и колонка в DGV была бы стоит знать. – Plutonix
@Plutonix: для воспроизведения этого не требуется ничего особенного (также он компилируется с опцией strict). Я включил подробный список шагов в вопросе; Я также включил код 'DataGridViewAdvButtonCell'. – Andreas