將 `Form1.ColorToolStripMenuItem.Visible = False` 等代碼左側作為字符串存入數據庫,運行時讀取字符串動態設置控件屬性。
' 數據庫存儲字符串: "ColorToolStripMenuItem" 或 "Button3"
Dim ctrlName As String = reader.GetString("ControlName") ' 讀取 "ColorToolStripMenuItem"
' 當前窗體查找
Dim ctrl As Control = Me.Controls(ctrlName)
If ctrl IsNot Nothing Then
ctrl.Visible = False
Else
' 可能在容器中(Panel/GroupBox/ToolStrip),需遞歸查找
ctrl = FindControlRecursive(Me, ctrlName)
End If
' 遞歸查找輔助函數
Function FindControlRecursive(parent As Control, name As String) As Control
If parent.Name = name Then Return parent
For Each c As Control In parent.Controls
Dim found = FindControlRecursive(c, name)
If found IsNot Nothing Then Return found
Next
Return Nothing
End Function
' 字符串格式: "Form1.ColorToolStripMenuItem" 或 "Form2.Button3"
Dim fullName As String = reader.GetString("FullControlPath")
Dim parts = fullName.Split("."c)
Dim formName = parts(0) ' "Form1"
Dim ctrlName = parts(1) ' "ColorToolStripMenuItem"
' 獲取窗體類型 (假設在同一程序集)
Dim formType = Assembly.GetExecutingAssembly().GetTypes() _
.FirstOrDefault(Function(t) t.Name = formName)
If formType IsNot Nothing Then
' 獲取靜態實例字段 (WinForms 默認實例)
Dim formInstance = formType.GetField(formName,
Reflection.BindingFlags.Static Or Reflection.BindingFlags.Public) _
.GetValue(Nothing)
If formInstance IsNot Nothing Then
Dim ctrlField = formType.GetField(ctrlName,
Reflection.BindingFlags.Instance Or Reflection.BindingFlags.Public Or Reflection.BindingFlags.NonPublic)
Dim ctrl = ctrlField.GetValue(formInstance)
If ctrl IsNot Nothing Then
ctrl.GetType().GetProperty("Visible").SetValue(ctrl, False)
End If
End If
End If
| 維度 | Controls 集合 | 反射 |
|---|---|---|
| 性能 | 極快 (O(1) 索引) | 較慢 (元數據查找) |
| 跨窗體 | 需傳遞 Form 實例 | 天然支援類名定位 |
| 容器嵌套 | 需遞歸查找 | 同樣需遞歸或完整路徑 |
| 類型安全 | 運行時發現錯誤 | 可編譯期驗證字段名 |
| 推薦場景 | 同窗體、簡單權限控制 | 插件架構、跨模塊、配置驅動 |
CREATE TABLE UiPermission (
Id INT PRIMARY KEY,
RoleId INT NOT NULL,
FormName NVARCHAR(100) NOT NULL, -- "Form1"
ControlName NVARCHAR(100) NOT NULL, -- "ColorToolStripMenuItem"
PropertyName NVARCHAR(50) NOT NULL, -- "Visible"
PropertyValue NVARCHAR(50) NOT NULL, -- "False"
CONSTRAINT UQ_Role_Control UNIQUE (RoleId, FormName, ControlName, PropertyName)
);
VB.NET 動態字符串操作控件:**同窗體用 `Controls[\"name\"]` + 遞歸查找最簡捷;跨窗體/插件化用反射獲取 Field/Property**。建議數據庫存儲 `FormName.ControlName` 完整路徑,運行時解析並通過反射或 Controls 集合應用屬性值,實現靈活的權限/顯示控制。