Нужно ли явно распоряжаться настроенным контекстным меню - PullRequest
0 голосов
/ 08 ноября 2011

У меня есть класс clsContextPopUpMenu для создания ContextMenuStrip с некоторыми базовыми функциями (например, копией), которые я могу использовать в различных элементах управления.

    Friend Sub New(ByRef objControl As System.Windows.Forms.Control)

    m_objControlContainer = objControl
    m_mnuCopyCell2Clipboard = New ToolStripMenuItem("Copy Cell")
    m_PopupMenu = New ContextMenuStrip
    m_PopupMenu.Items.AddRange(New ToolStripMenuItem() {m_mnuCopyCell2Clipboard})
End Sub

Например, я могу использовать его в DataGridView DGVTable:

 Private m_objPopUpMenu As clsContextPopUpMenu
 m_objPopUpMenu = New clsContextPopUpMenu(CType(DGVTable, System.Windows.Forms.Control))

Однако обратите внимание, что m_objPopUpMenu НЕ связано с формой, имеющей вышеуказанное представление данных. Согласно объяснению конструктора ContextMenuStrip в MSDN , я думаю, что m_objPopUpMenu не может быть удален автоматически, поскольку он не является дочерним элементом формы.

У меня вопрос: нужно ли явно указывать m_objPopUpMenu в конструкторе:

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)
    Try
        If disposing AndAlso components IsNot Nothing Then
            components.Dispose()
            **m_objPopUpMenu.Dispose()**
        End If
    Finally
        MyBase.Dispose(disposing)
    End Try
End Sub

Более широкий вопрос заключается в том, когда я должен сам распоряжаться объектами / ресурсами? Конечно, сборщик gc не волшебник, чтобы освободить всю доступную память. Могу ли я всегда располагать объекты / ресурсы в Dispose Sub, как показано выше?

1 Ответ

1 голос
/ 08 ноября 2011

Пересмотренный ответ для лучшего понимания вопроса:

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

Вот ревизия вашего класса, которая будет поддерживать автоматическое удаление так же, как и окна, если бы вы добавили ContextMenuStrip непосредственно в форму:

Friend Sub New(ByVal objControl As System.Windows.Forms.Control, ByVal components As System.ComponentModel.IContainer)

    m_objControlContainer = objControl
    m_mnuCopyCell2Clipboard = New ToolStripMenuItem("Copy Cell")
    m_PopupMenu = New ContextMenuStrip(components)
    m_PopupMenu.Items.AddRange(New ToolStripMenuItem() {m_mnuCopyCell2Clipboard})
End Sub

Чтобы вызвать этот новый конструктор из вашей формы или пользовательского элемента управления:

 Private m_objPopUpMenu As clsContextPopUpMenu
 m_objPopUpMenu = New clsContextPopUpMenu(DGVTable, Me.components)

Обратите внимание, что я также удалил ByRef из конструктора, поскольку он не требуется, что также устраняет необходимость приведения элементов управления перед передачей их конструктору.

Еще одно примечание: раньше («в прошлое») компоненты не обязательно присутствовали в каждой форме или пользовательском элементе управления. Я считаю, что это изменилось / было исправлено, но если вы обнаружите, что без него, это легко добавить вручную:

Private components As System.ComponentModel.IContainer

В вашем конструкторе:

Me.components = New System.ComponentModel.Container()

В вашем методе Dispose (я добавил метод полного удаления, если его еще нет; если он есть, просто добавил код, связанный с компонентами):

Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
    If disposing Then
        If Not (components Is Nothing) Then
            components.Dispose()
        End If
    End If
    MyBase.Dispose(disposing)
End Sub
...