使列表中的按钮向方法发送唯一数据

时间:2015-01-13 21:00:09

标签: c# winforms list button methods

我制作了一个应用程序,它会在网格中放置按钮,用户可以在其中指定游戏区应该有多大。 我在列表中创建按钮,指定一些数据,如backgroundimage,size和location。然后,我需要以某种方式使不同的按钮执行不同的代码。我想我可以用一种方法做到这一点,(如果没有任何好方法以编程方式创建方法),如果我能以某种方式使按钮向方法发送一条独特的信息来识别按下哪个按钮。

    public void buttonplacer()
    {
        int nbrofbtns = Form2.puzzlesize * Form2.puzzlesize;



        List<Button> btnslist = new List<Button>();
        for (int i = 0; i < nbrofbtns; i++)
        {

            Button newButton = new Button();
            btnslist.Add(newButton);
            this.Controls.Add(newButton);

            newButton.Name = "btn" + i.ToString();
            newButton.Width = btnsidelength;
            newButton.Height = btnsidelength;
            newButton.Top = btnsidelength * Convert.ToInt32(Math.Floor(Convert.ToDouble(i / Form2.puzzlesize)));
            newButton.Left = btnsidelength * Convert.ToInt32(Math.Floor(Convert.ToDouble(i)) - Math.Floor((Convert.ToDouble(i)) / (Form2.puzzlesize)) * (Form2.puzzlesize));
            newButton.BackgroundImage = Lights_out_.Properties.Resources.LightsOutBlack;




            newButton.Click += new EventHandler(Any_Button_Click);
        }
    }
    void Any_Button_Click(object sender, EventArgs e)
    {

    }

(如果你想知道我正在做一个名为&#34的游戏; Light&#39; s&#34;&#34;) 提前谢谢!

3 个答案:

答案 0 :(得分:3)

Any_Button_Click方法收到object sender 点击的按钮。您只需将其转换为Button

void Any_Button_Click(object sender, EventArgs e)
{
    Button b = (Button)sender;
    // do stuff here
}

您可以使用按钮的Location属性来确定它在游戏板上的位置,或者您可以使用Tag在初始化时选择的任何信息为按钮分配任意对象这样的财产:

button.Tag = "someHelpfulString";

或者像这样:

button.Tag = new Tuple<int, int>(xpos, ypos);

(其中xposypos是按钮网格中的位置)

或者像这样:

button.Tag = new ButtonInfoObject(foo, bar, baz);

(这取决于您定义ButtonInfoObject类。)

答案 1 :(得分:1)

作为其他答案的替代方案,特别是在某种程度上解决了部分&#34;以编程方式创建方法的好方法&#34;,C#语言的一部分称为Lambda Expressions。长话短说,你可以写下这些内容:

newButton.Click += (s, e) =>
{
    //here you have access to all variables accessible in current scope,
    //including "newButton" and "i";
    //you could, for example, call some method passing "i" as an argument
    //or just put that method's code inside this block
};

这种方法的唯一缺点是,如果您计划稍后取消注册处理程序,则需要格外小心(请参阅this questionthis question以供参考)。

修改

正如评论中指出的那样,我忽略了i保留在整个for循环范围内的事实,因此在lambda中使用它几乎是没有意义的(所有处理程序都会使用它的#final值)。为了使其行为与预期一样,可以简单地在循环内定义一个变量,使其在每次迭代结束时超出范围,并为每个处理程序单独存储:

var btnNo = i;
newButton.Click += (s, e) =>
{
    //use "btnNo" instead of "i"
    //you can still safely use "newButton" reference
    //since it's defined inside the loop
}

答案 2 :(得分:-1)

使用sender对象获取按下的按钮名称:

void Any_Button_Click(object sender, EventArgs e)
{
     switch ((sender as Button).Name)
     {
         case "btn0":
             //...
             break;
         case "btn1":
             //...
             break;
         //...
     }
}