Do I need to explicitly dispose a customized contextmenustrip - vb.net

I have a class clsContextPopUpMenu to create a ContextMenuStrip with some basic functions (e.g.copy) that I can use in different controls.
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
For example, I can use it in a DataGridView DGVTable:
Private m_objPopUpMenu As clsContextPopUpMenu
m_objPopUpMenu = New clsContextPopUpMenu(CType(DGVTable, System.Windows.Forms.Control))
However, note that m_objPopUpMenu IS NOT associated with the form having the above datagridview. According to ContextMenuStrip constructor explanation in MSDN, I think that m_objPopUpMenu cannot be disposed automatically since it is not a child of the form.
My question is, do I have to explicitly dispose m_objPopUpMenu in designer:
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
A broader question is that when should I dispose objects/resource by myself? Of course, gc collector is not a magician to release all available memory. Can I always dispose objects/resource in Dispose Sub as shown above?

Revised answer due to better understanding of issue:
Because the ContextMenuStrip implements IDisposable, you will either need to add it to the list of Components managed by the form so that it is disposed appropriately and automatically or manage the disposal yourself as suggested in your original question.
Here is a revision of your class that will support the automatic disposal in the same way that windows would handle it if you were to add ContextMenuStrip directly to the form:
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
To call this new constructor from within your form or user control:
Private m_objPopUpMenu As clsContextPopUpMenu
m_objPopUpMenu = New clsContextPopUpMenu(DGVTable, Me.components)
Note that I also removed the ByRef from the constructor since it is not required, which also eliminates the need to cast the controls before passing them to the constructor.
One additional note: it used to be ("back in the day") that components was not necessarily present on every form or user control. I believe that this has changed/been fixed, but if you find yourself without, it is easy to add manually:
Private components As System.ComponentModel.IContainer
In your constructor:
Me.components = New System.ComponentModel.Container()
In your Dispose method (I have added the full dispose method in case it is not already present; if it is, just added the components-related code):
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

Related

ListViewGroup shows items but not headers

I have read through several forums and tried different options. Most of the answers were this, which makes me assume that would be the issue. I placed Application.EnableVisualStyles()
at the beginning of InitializeComponent() in the .Designer.vb file as seen below:
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()>
Partial Class MetadataCollectionGUI
Inherits System.Windows.Forms.Form
'Form overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()>
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()
Application.EnableVisualStyles() ' <--- See Here
Me.ListViewMetaDataCollection = New System.Windows.Forms.ListView()
Me.ColumnTags = CType(New System.Windows.Forms.ColumnHeader(), System.Windows.Forms.ColumnHeader)
etc... etc...
End Sub
Etc...
End Class
Did I misunderstand how to execute that particular solution or is the issue something different?
I found out what the issue was. Go to the project properties and enable the application framework. Now you can enabled the XP visual styles.
Thank you Hursey & jmcilhinney, I would not have figured it out without you all!

Prevent developer from placing a UserControl more than one time in Design Time

I am working on a UserControl and I am looking for a way to prevent developer to place this UserControl more than one time into a form. All this in Design Time. In other words, how can I detect if my UserControl is already placed into ParentForm or not, in Design Time(!!!), and prevent the second placement if there is already one there?
I tried something like this example below... First I am not sure if this is the "correct" way and second I can't find how to remove or stop the placement of UserControl in case there is already one.
Again, all this, in Design Time!!!
Private Sub MyUserControl_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim _Count As Integer
Dim _UserControl As MyUserControl
For Each _UserControl In Me.ParentForm.Controls
If _UserControl.Name.Contains("MyUserControl") Then
_Count += 1
End If
Next
If _Count > 1 Then
MsgBox("Control have been placed.")
Else
MsgBox("Control haven't placed yet.")
End If
End Sub
for this same form is easy use new and dispose, it not work in beat weans forms. only in this same. U can use mutex or some singleton instant of this module property or other inform method that this was created and when was disposed.
Sub New()
' This call is required by the designer.
InitializeComponent()
If Not co Is Nothing Then Throw New Exception
co = Me ' assign public propert in module or singleton
' Add any initialization after the InitializeComponent() call.
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
co = Nothing
MyBase.Dispose(disposing)
End Try
End Sub
Module common
Property co As UserControl1
End Module
Finnaly I ended to this...
Private Sub Me_ParentChanged(sender As Object, e As EventArgs) Handles Me.ParentChanged
Dim _ParentForm = DirectCast(Me.FindForm, Control)
Dim _ControlName As String
If _ParentForm IsNot Nothing Then
For Each _Control As Control In _ParentForm.Controls
If TypeOf _Control Is MyUserControl AndAlso _Control IsNot Me Then
Throw New ArgumentOutOfRangeException("", "You can place only one " & _ControlName & " control per form.")
End If
_Control = _ParentForm.GetNextControl(_Control, True)
Next
End If
End Sub

Form designer differs for custom form

I'm new to .net and I am developing my library dll testing it against a test application for gaining experience etc.... I apologize in advance if I am not using the correct terms in my message.
As I want to add some custom properties to all my future forms I created a custom form with some extra properties.
I then create a form based on the new custom form and compared the .designer.vb files. I found that changing inherits system.windows.forms.form to inherits library.Myform should do it but I also found another difference:
Both designer files contain code to dispose components however they are slightly different:
designer generated for form based on system.windows.forms.form:
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
the one for the form based on library.Myform:
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub
Why that difference and should I modify my forms created from the custom form so that they contain the Try-Finally block. If yes is there a way to change the behavior of vs to do it when creating the form based on the custom form.

Changing the color of a selected item in a listbox/listview

I'm reasonably new to programming and soon I will be creating a program and would like to change the colour of a selected row via a button click.
I have been attempting this but I don't even know where to begin. If someone could point me in the correct direction it would be much appreciated.
Thanks ^.^
You could simply create a new control, then change the designer to inherit from the listbox control.
the designer code would then look something like this (vs2010):
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class UserControl1
Inherits ListBox
'UserControl overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
End Class
To see the designer code, select "Show All Files" (button at the top of your solution explorer). Then expand the new control node in your solution explorer.
then change the line:
Inherits System.Windows.Forms.UserControl
to:
Inherits ListBox
and finally delete delete the line:
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Hope that helps.

Non modal form that blocks its Owner

I was trying to get forms configuration for my project that can suit my needs here and didn't get to a solution. It seem's I find a solution and now I have to implement it application-wide.
Here I have main form and a few subforms (which have many subforms) and through the main form I should ALWAYS be able to close all opened forms, watch for universal keypresses, close application permanently and watch for critical events.
I find solution in this facts:
From main form I open main subforms instantiated but non modally.
From sub forms I open deeper subforms also instantiated and non modally.
In all those subforms _Load event handler I disable calling form and in _FormClosing handler I enable it again. That way non modal forms act like modal forms in order to caller but not in order to main form which stays responsive all the time!
In forms that have to block its own caller (Owner) I added property "Blocking" so that my code looks like this:
If Not formIsOpened(frm_myFirstChild) Then
Dim f As New frm_myFirstChild
f.Blocking = True
f.Show(Me)
f = Nothing
End If
In the frm_myFirstChild I have property:
<Browsable(True), _
DefaultValue(False)> _
Public Property Blocking() As Boolean
Get
Return _Blocking
End Get
Set(ByVal value As Boolean)
_Blocking = value
End Set
End Property
If boolean property "Blocking" is TRUE then under _Load this code has to be executed:
If Blocking And Me.Owner IsNot Nothing Then
Me.Owner.Enabled = False
End If
In _FormClosing that:
If Blocking And Me.Owner IsNot Nothing Then
Me.Owner.Enabled = True
Me.Owner.Activate()
End If
All of that work as expected so I try to implement that for all forms and use when needed in a subclass "cls_transform":
Protected Overrides Sub OnFormClosing(ByVal e As System.Windows.Forms.FormClosingEventArgs)
If Blocking And Me.Owner IsNot Nothing Then
Me.Owner.Enabled = True
Me.Owner.Activate()
End If
MyBase.OnFormClosing(e)
End Sub
Protected Overrides Sub OnLoad(ByVal e As System.EventArgs)
If Blocking And Me.Owner IsNot Nothing Then
Me.Owner.Enabled = False
End If
MyBase.OnLoad(e)
End Sub
Here I have problem that subclass doesn't understand the property Blocked (not declared).
How do you get a Form's property Blocked to subclass so I can use those subclasses for all forms, and switch the property Blocking from the outside regarding functionality needs?
Sounds to me that "cls_transform" is actually a class derived from Form, the only way that OnFormClosing could work. Which is okay, your "sub-forms" now need to derive from cls_transform instead of Form. Do pick a better name.
Then simply add the Blocking property to that cls_transform class to solve your problem.
Do note that there's a bug in your OnFormClosing method. It can be canceled and that will leave the form opened with its owner in the wrong state. You need to write it like this instead:
Protected Overrides Sub OnFormClosing(ByVal e As System.Windows.Forms.FormClosingEventArgs)
MyBase.OnFormClosing(e)
If Not e.Cancel And Blocking And Me.Owner IsNot Nothing Then
Me.Owner.Enabled = True
Me.Owner.Activate()
End If
End Sub