WinForms动态创建CheckBox:变量命名事件处理程序及控件访问问题
WinForms动态创建CheckBox的两个问题解决方案
一、无法通过Name属性直接引用控件的问题
动态创建的CheckBox不会自动生成类级别的成员变量,编译器无法识别chkAllowColumnReorder这类名称,解决方式有两种:
- 从父控件的Controls集合中查找
创建完成后,通过控件Name从parentControl.Controls中获取实例:
CheckBox chkAllowColumnReorder = parentControl.Controls["chkAllowColumnReorder"] as CheckBox; if(chkAllowColumnReorder != null) { // 执行后续操作 }
- 创建时将控件存入字典缓存
如果需要频繁访问控件,可以在方法外定义字典,创建控件时保存引用:
private Dictionary<string, CheckBox> _checkBoxCache = new Dictionary<string, CheckBox>(); void CreateCheckBoxes(Control parentControl, int left, int top, int lineSpace) { List<string> listVariables = new List<string>() { "AllowColumnReorder", "CaptureFocusClick", "ColScaleMode", "ColumnTracking", "RowTracking", "EnsureVisible", "FullRowSelect", "GridLines", "HideSelection", "HoverSelection", "IsFocused", "LabelEdit", "MultiSelect", "Scrollable", "VisualStyles" }; foreach (string varName in listVariables) { CheckBox ctlTemp = new CheckBox { Name = "chk" + varName, Text = varName, Top = top, Left = left }; parentControl.Controls.Add(ctlTemp); _checkBoxCache.Add(ctlTemp.Name, ctlTemp); top += lineSpace; } // 后续通过字典快速获取控件 if(_checkBoxCache.TryGetValue("chkAllowColumnReorder", out var targetChk)) { // 操作targetChk } }
关于调试时Name显示窗体名称:你大概率是选错了监视对象,确保监视的是ctlTemp.Name,而非当前窗体(this)的Name属性。
二、绑定对应名称的CheckedChanged事件处理程序
因为你的事件处理程序按chk{VarName}_CheckedChanged命名(比如chkAllowColumnReorder_CheckedChanged),可以通过反射在创建控件时自动绑定:
void CreateCheckBoxes(Control parentControl, int left, int top, int lineSpace) { List<string> listVariables = new List<string>() { "AllowColumnReorder", "CaptureFocusClick", "ColScaleMode", "ColumnTracking", "RowTracking", "EnsureVisible", "FullRowSelect", "GridLines", "HideSelection", "HoverSelection", "IsFocused", "LabelEdit", "MultiSelect", "Scrollable", "VisualStyles" }; foreach (string varName in listVariables) { CheckBox ctlTemp = new CheckBox { Name = "chk" + varName, Text = varName, Top = top, Left = left }; parentControl.Controls.Add(ctlTemp); // 拼接事件处理程序名称 string handlerName = $"{ctlTemp.Name}_CheckedChanged"; // 通过反射获取对应方法 MethodInfo method = this.GetType().GetMethod(handlerName, BindingFlags.Instance | BindingFlags.NonPublic); if(method != null) { // 转换为EventHandler委托并绑定 EventHandler eventHandler = (EventHandler)Delegate.CreateDelegate(typeof(EventHandler), this, method); ctlTemp.CheckedChanged += eventHandler; } top += lineSpace; } }
注意:事件处理程序的签名必须是标准的void 方法名(object sender, EventArgs e),否则反射无法创建委托。
内容的提问来源于stack exchange,提问作者Jeff-Gaines
相关产品推荐
相关产品推荐

