如何创建带索引的事件处理程序以区分动态生成的按钮控件
解决方案分为两种常用实现方式,你可以根据业务需求选择:
方案1:共用同一个事件处理程序,通过标识区分触发按钮
这是最简洁也最推荐的写法,只需要给每个按钮增加一个标识存储索引即可:
- 在创建按钮的循环中,给
Tag属性赋值当前索引:
private Button[] butRelays = new Button[8]; for (int i = 0; i < butRelays.Length; ++i) { butRelays[i] = new Button(); butRelays[i].Text = "R" + (i + 1); butRelays[i].Width = 31; butRelays[i].Height = 62; butRelays[i].Top = 19; butRelays[i].Left = 6 + 30 * i; // 新增这行,把索引存到Tag属性里 butRelays[i].Tag = i; grpRelays.Controls.Add(butRelays[i]); this.butRelays[i].Click += new System.EventHandler(this.butRelays_Click); }
- 在共用的事件处理方法中,通过
sender拿到触发按钮,读取索引即可区分:
private void butRelays_Click(object sender, EventArgs e) { Button clickedButton = sender as Button; if (clickedButton == null) return; // 读取之前存的索引 int relayIndex = (int)clickedButton.Tag; // 后续根据索引写对应业务逻辑即可 }
方案2:通过Lambda闭包直接绑定单独逻辑
如果需要每个按钮有完全独立的处理逻辑时,可以用这种方式,完全可以替代你期望的`butRelays[i]_Click的效果,不需要单独写多个方法:
注意:必须在循环内部定义临时变量存储索引,避免闭包共享变量的坑,导致所有按钮拿到的索引都是最终值
private Button[] butRelays = new Button[8]; for (int i = 0; i < butRelays.Length; ++i) { // 必须在循环内定义临时变量捕获当前索引 int currentIndex = i; butRelays[i] = new Button(); butRelays[i].Text = "R" + (i + 1); butRelays[i].Width = 31; butRelays[i].Height = 62; butRelays[i].Top = 19; butRelays[i].Left = 6 + 30 * i; grpRelays.Controls.Add(butRelays[i]); // 直接绑定Lambda作为事件处理,currentIndex就是当前按钮的索引 butRelays[i].Click += (s, args) => { // 这里直接写对应索引按钮的处理逻辑即可,currentIndex对应当前按钮索引 // 比如触发第currentIndex+1号继电器的开关逻辑 }; }
你提到的this.butRelays[i].Click += new System.EventHandler(this.butRelays[i]_Click);这种写法C#语法不支持,编译器无法根据变量动态匹配方法名,上面两种方案已经可以覆盖所有需求场景,性能和可维护性也更高。
内容的提问来源于stack exchange,提问作者ABP
相关产品推荐
相关产品推荐

