如何将二维按钮数组的索引传递给EventHandler?
解决按钮点击时获取棋盘索引的问题
嘿,我来帮你搞定这个问题!你的核心需求是点击棋盘按钮时拿到对应的[i,j]索引,进而操作valueBtn数组,咱们先看看原代码里的几个关键问题,再一步步修正:
原代码的问题点
valueBtn作用域错误:你在内部循环里声明了valueBtn,这意味着每次循环都会新建一个独立的6x6数组,循环结束后这些数组都会被销毁,而且每个按钮对应的数组都是单独的,完全没法实现全局的棋盘值存储。- 事件绑定位置错误:
btn[i,j].Click += btnPress;放在了双层循环外面,这时候循环已经结束,i和j的值都是6(超出了数组的索引范围,因为数组是从0到5),不仅会报错,而且根本没给每个按钮绑定点击事件。 - 缺少索引关联:没有把按钮和对应的[i,j]索引绑定起来,所以点击时没法知道哪个按钮对应哪个位置。
修改后的完整代码示例
首先,把valueBtn改成类的成员变量,这样整个类的方法都能访问它:
// 在类的顶部声明成员变量 private Button[,] btn; private int[,] valueBtn; private int currentI, currentJ; // 用来记录当前点击的按钮索引,供drawValue使用 public void board(object obj, EventArgs ea) { int n = 6; btn = new Button[n, n]; valueBtn = new int[n, n]; // 在这里初始化全局的二维数组 // 初始化valueBtn的值(这里先全部设为0,你可以根据需求修改) for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { valueBtn[i, j] = 0; } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { int p = 60 * i + 100; int q = 60 * j + 100; btn[i, j] = new Button(); btn[i, j].Location = new Point(p, q); btn[i, j].Size = new Size(60, 60); // 把[i,j]索引存到按钮的Tag属性里,C#7+支持值元组写法 btn[i, j].Tag = (i, j); // 给每个按钮绑定点击事件 btn[i, j].Click += btnPress; this.Controls.Add(btn[i, j]); } } // 只绑定一次Paint事件,避免多次点击重复绑定 this.Paint += drawValue; } public void btnPress(object sender, EventArgs ea) { Button pressedBtn = sender as Button; if (pressedBtn != null && pressedBtn.Tag is (int i, int j)) { // 拿到点击按钮的[i,j]索引 currentI = i; currentJ = j; // 获取对应valueBtn的值 int currentValue = valueBtn[i, j]; // 触发Paint事件,调用drawValue绘制 this.Invalidate(); } } // 示例的drawValue方法,你可以根据需求修改绘制逻辑 public void drawValue(object sender, PaintEventArgs e) { // 用currentI和currentJ获取要绘制的值 int valueToDraw = valueBtn[currentI, currentJ]; // 示例:在窗体上绘制值,位置可以自己调整 e.Graphics.DrawString(valueToDraw.ToString(), new Font("Arial", 12), Brushes.Black, new PointF(20, 20)); }
关键修改说明
- 成员变量重构:把
btn和valueBtn都改成类的成员变量,确保所有方法都能访问到同一个棋盘数组。 - Tag存储索引:利用Button的
Tag属性存储对应的[i,j]索引,这里用了C#7+的值元组写法,简洁方便;如果你用的是旧版本C#,可以用Tuple<int, int>代替,比如btn[i,j].Tag = Tuple.Create(i, j);,然后在btnPress里解析:var tuple = pressedBtn.Tag as Tuple<int, int>; int i = tuple.Item1; int j = tuple.Item2;。 - 修正事件绑定:把
Click事件绑定放到内部循环里,确保每个按钮都能触发点击事件。 - 优化Paint事件绑定:只在
board方法里绑定一次Paint事件,每次点击后调用Invalidate()触发重绘,避免多次绑定导致重复绘制。 - 索引解析:在
btnPress里通过Tag解析出[i,j],然后就能直接访问valueBtn[i,j]的值了。
这样修改后,你点击任意按钮时,就能准确拿到对应的索引和数组值,然后在drawValue里完成绘制啦!
内容的提问来源于stack exchange,提问作者yungCalculator
相关产品推荐
相关产品推荐

