简体   繁体   中英

Access and disable ToolStripItems (ToolStripButtons, ToolStripMenuItems) using their names

I would like to disable UI elements (Controls, Components etc.) which names are stored in a database.
My code works for Controls, but I would like to access (to disable them) ToolStripItems such as ToolStripButtons, ToolStripMenuItems etc..

This is my current code:

Dim df_command As New SqlCommand("select * from treftab where ref_data = 'INTERVENTION' and ref_code  = '0'", sfacon)
Dim df_reader As SqlDataReader = df_command.ExecuteReader

If df_reader.HasRows Then
    While df_reader.Read
        Dim reftext As String = df_reader("ref_text")
        Dim someVariable As Control = Nothing
        Dim SearchedControls = Me.Controls.Find(key:=reftext, searchAllChildren:=True)
        someVariable = SearchedControls(0)
        someVariable.Enabled = False
    End While
End If

You cannot find ToolStrip or MenuStrip Items in the Form.Control collection because those UI elements are not Controls but a special breed of Components.
While ToolStrip and MenuStrip both inherit from Control, ToolStripMenuItems inherit from Component and ToolStripItem (the latter provides the Enabled property).

You could build a Dictionary(Of String, Boolean) containing the names of the UI elements to enable or disable, based on values stored in the data source you have.

The use a method that reads the current Form's Fields, loop the KeyValuePairs in the Dictionary to find elements matching the Dictionary Keys and sets the Enable property based on the corresponding Values .

For example, to disabled all the elements in the collection:
(I assume you have stored all different names per each Form in your data source)

Dim names As New Dictionary(Of String, Boolean)()    

' [...]
While df_reader.Read()
    names.Add(df_reader("ref_text").ToString(), False)
End While

EnableDisableFormElements(Me, names)

The method use Type.GetFields() to find all non public instance fields of the specified Form, the FieldInfo.GetValue() to get the instance of a UI element represented by that Field.

It then determines whether the UI element is a Control or a ToolStripItem (UI elements that inherit from these base classes have an Enabled property) and sets it using the Value stored in the Dictionary.

TrimStart("_"c) is there because VB.Net has the (IMO) bad habit to add an underscore to these Field names. It doesn't happen using C#.

Imports System.Reflection
Imports System.Windows.Forms

Private Sub EnableDisableFormElements(parentForm As Form, elementNames As Dictionary(Of String, Boolean))
    Dim allFields = parentForm.GetType().GetFields(BindingFlags.NonPublic Or BindingFlags.Instance)

    For Each element As KeyValuePair(Of String, Boolean) In elementNames
        Dim searchElement = allFields.FirstOrDefault(
        Function(f) f.Name.TrimStart("_"c).Equals(element.Key)).GetValue(parentForm)

        If searchElement IsNot Nothing Then
            If TypeOf searchElement Is Control Then
                DirectCast(searchElement, Control).Enabled = element.Value
            ElseIf TypeOf searchElement Is ToolStripItem Then
                DirectCast(searchElement, ToolStripItem).Enabled = element.Value
            End If
        End If
    Next
End Sub

The items collection of the ToolStrip and the derived controls, MenuStrip , ContextMenuStrip , StatusStrip is the ToolStripItemCollection which has a Find method for the deep search just like the ControlCollection.Find method. So you have to search this collection through the Items properties of the mentioned controls for a ToolStripItem or any derived type.

Create a search function for the mentioned classes:

Public Function GetToolStripItem(toolStrip As ToolStrip, key As String) As ToolStripItem
    Return toolStrip.Items.Find(key, True).FirstOrDefault
End Function

... and call it as follows:

'Search a MenuStrip
Dim tsi = GetToolStripItem(MenuStrip1, key)

'Search a ToolStrip
Dim tsi = GetToolStripItem(ToolStrip1, key)

'Search a ContextMenuStrip
Dim tsi = GetToolStripItem(ContextMenuStrip1, key)

'Search a StatusStrip
Dim tsi = GetToolStripItem(StatusStrip1, key)

If tsi IsNot Nothing Then
    tsi.Enabled = False
End If

Also, you can use the TypeOf operator to determine the type of an item:

If TypeOf tsi Is ToolStripMenuItem Then
    '...
End If

If TypeOf tsi Is ToolStripDropDownItem Then
    '...
End If

If TypeOf tsi Is ToolStripButton Then
    '...
End If

... and use the iterator functions to get all or a specific type of items from the collections:

Public Iterator Function GetAllToolStripItems(items As ToolStripItemCollection) As _
    IEnumerable(Of ToolStripItem)
    For Each tsi As ToolStripItem In items
        Yield tsi

        If TypeOf tsi Is ToolStripDropDownItem Then
            For Each ddi As ToolStripItem In
            GetAllToolStripItems(DirectCast(tsi, ToolStripDropDownItem).DropDownItems)
                Yield ddi
            Next
        End If
    Next
End Function

Public Iterator Function GetAllToolStripItems(Of T)(items As ToolStripItemCollection) As _
    IEnumerable(Of T)
    For Each tsi In items
        If TypeOf tsi Is T Then
            Yield DirectCast(tsi, T)
        ElseIf TypeOf tsi Is ToolStripDropDownItem Then
            For Each ddi In
            GetAllToolStripItems(Of T)(DirectCast(tsi, ToolStripDropDownItem).DropDownItems)
                Yield ddi
            Next
        End If
    Next
End Function

... and the usage:

'Get them all...
Dim items = GetAllToolStripItems(TooStrip1.Items) 'or any derived control...

'Get for example the ToolStripComboBox items...
Dim items = GetAllToolStripItems(Of ToolStripComboBox)(MenuStrip1.Items)

Note that in the iterators, identifying the ToolStripDropDownItem is necessary to get the ToolStripItemCollection of derived classes including:

Each of which inherits the DropDownItems property which of course should be passed to the iterator.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM