簡體   English   中英

使用名稱訪問和禁用 ToolStripItems(ToolStripButtons、ToolStripMenuItems)

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

我想禁用名稱存儲在數據庫中的 UI 元素(控件、組件等)。
我的代碼適用於控件,但我想訪問(禁用它們)ToolStripItems,例如 ToolStripButtons、ToolStripMenuItems 等。

這是我當前的代碼:

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

在 Form.Control 集合中找不到 ToolStrip 或 MenuStrip 項,因為這些 UI 元素不是控件,而是一種特殊的組件。
雖然 ToolStrip 和 MenuStrip 都繼承自 Control,但 ToolStripMenuItems 繼承自 Component 和ToolStripItem (后者提供Enabled屬性)。

您可以根據存儲在您擁有的數據源中的值構建一個包含要啟用或禁用的 UI 元素名稱的Dictionary(Of String, Boolean)

使用讀取當前 Form 的 Fields 的方法,循環 Dictionary 中的KeyValuePairs以查找與 Dictionary Keys匹配的元素,並根據相應的Values設置Enable屬性。

例如,禁用集合中的所有元素:
(我假設您在數據源中為每個表單存儲了所有不同的名稱)

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)

該方法使用Type.GetFields()查找指定Form 的所有非公共實例字段, FieldInfo.GetValue()獲取該字段表示的UI 元素的實例。

然后,它確定 UI 元素是 Control 還是 ToolStripItem(從這些基類繼承的 UI 元素具有Enabled屬性)並使用存儲在 Dictionary 中的 Value 對其進行設置。

TrimStart("_"c)之所以存在,是因為 VB.Net 有(IMO)在這些字段名稱中添加下划線的壞習慣。 使用 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

ToolStrip和派生控件MenuStripContextMenuStripStatusStrip的項目集合是ToolStripItemCollection ,它具有用於深度搜索的Find方法,就像ControlCollection.Find方法一樣。 因此,您必須通過上述控件的Items屬性搜索此集合,以查找ToolStripItem或任何派生類型。

為上述類創建搜索 function:

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

...並按如下方式調用它:

'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

此外,您可以使用TypeOf運算符來確定項目的類型:

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

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

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

...並使用迭代器函數從 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

...以及用法:

'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)

請注意,在迭代器中,識別ToolStripDropDownItem是獲取派生類的ToolStripItemCollection所必需的,包括:

每個都繼承DropDownItems屬性,當然應該將其傳遞給迭代器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM