UserControl uc = new UserControl();
int len = 1024 * 10;
uc.Size = new System.Drawing.Size(len, len);
for (int i = 0; i < 50; i++)
{
Button button = new Button();
//button里面的文字是正确的
button.Text = "Test"+i;
button.Top = i *32;
button.Click += (o1, e1) =>
{
//点击每个按钮后都显示的都是Test50,怎么不是对应的序列?
MessageBox.Show("Test" + i);
}; uc.Controls.Add(button);
}
ActionsPane.Controls.Add(uc);
int len = 1024 * 10;
uc.Size = new System.Drawing.Size(len, len);
for (int i = 0; i < 50; i++)
{
Button button = new Button();
//button里面的文字是正确的
button.Text = "Test"+i;
button.Top = i *32;
button.Click += (o1, e1) =>
{
//点击每个按钮后都显示的都是Test50,怎么不是对应的序列?
MessageBox.Show("Test" + i);
}; uc.Controls.Add(button);
}
ActionsPane.Controls.Add(uc);
解决方案 »
- 关于窗体之间的数据传递
- using(...)是啥意思?
- 求助!用C#直接读取DBF文件,不是用ODBC或OLE等
- 用第三方控件 生成用户控件时,如何让原控件属性在新生成的用户控件的属性窗口里显示出来
- System.Windows.Shapes.Rectangle与System.Drawing.Rectangle的区别
- XmlNode 只能添加子节点吗?
- 有没有精通socket 编程的朋友。留下你的QQ 或者 群,我要加入,一起学习!
- 阿房收集制作的技术资料电子书
- 日期格式的显示?
- Developer XtraTreeList第三方控件问题
- 静态加载tree 问题
- 关于Timer 传递参数的问题
你虽然循环了50次之多,但是button的位置都没有改变, 也就是说在一个位置上叠加了50个button。
只不过你看上去只有1个
当你点这个button的时候,时间上是调用了最后一个button的click事件。打印出来。当然是Test50了
int len = 1024 * 10;
uc.Size = new System.Drawing.Size(len, len);
for (int i = 0; i < 50; i++)
{
Button button = new Button();
//button里面的文字是正确的
button.Text = "Test"+i;
button.Top = i *32;
button.Tag=("Test" + i);
button.Click += (o1, e1) =>
{
//点击每个按钮后都显示的都是Test50,怎么不是对应的序列?
MessageBox.Show((o1 as Button).Tag as string);
}; uc.Controls.Add(button);
}
ActionsPane.Controls.Add(uc);
显示了50个button。
int len = 1024 * 10;
uc.Size = new System.Drawing.Size(len, len);
for (int i = 0; i < 50; i++)
{
Button button = new Button();
button.Text = "Test" + i;
button.Top = i * 32;
button.Tag = i;
button.Click += (o1, e1) =>
{
MessageBox.Show("Test" + button.Tag);
};
uc.Controls.Add(button);
}
panel1.Controls.Add(uc);
UserControl uc = new UserControl();
int len = 1024 * 10;
uc.Size = new System.Drawing.Size(len, len);
for (int i = 0; i <50; i++)
{
Button button = new Button();
button.Text = "Test"+i;
button.Top = i *32;
//这样也正确
int j = i;
button.Click += (o1, e1) =>
{
MessageBox.Show("Test" + j);
};
uc.Controls.Add(button);
}
ActionsPane.Controls.Add(uc);
很简单,lambda定义了一个匿名委托,实际上是一个方法,调用这个方法的时候,也就是按下按钮时,i已经等于50了,按下按钮时for循环已经退出,这时候i=50,如果你多事,在循环后加上一句i=10000;你会发现显示的是Test10000,
//点击每个按钮后都显示的都是Test50,怎么不是对应的序列?
MessageBox.Show("Test" + i);
};
这段代码相当于一个方法,此方法并不是每次循环都要执行的,而是每次触发click事件时才执行,所以循环中i是多少都没有意义,只有点击按钮时的i值才有效,点击时已经在49的基础上i++了,当然都是50
// TO: stonespace
// 我觉得 i 已经等于 50 的这个说法不准确,为什么?因为当 for 循环结束的时候,i 的值已经丢弃了,
// 当每次点击的时候,根本取的不是 i 的值。因为这个时候已经没有 i 了。
// 但事件中又确确实实是绑定了 i 的值,经过分析我觉得原因如下:// 在 Lamdha Expression 出现以前,要绑定事件必须先定义一个和事件具有相同签名的函数
// 就像这样:
private void ButtonClick(object sender, EventArgs e)
{
......
}// 楼主程序中出现了 i,也就是说在 ButtonClick 方法内部使用了 i,而通过方法的签名可以得知,
// 入参并没有 i,这个 i 是哪来的,他如何才能进入 ButtonClick 方法内部?
// 很明显,Lamdha 在内部实现的时候使用了类似于全局变量的实现方式,也就是说,
// 在方法外面,定义全局实例变量,假设叫 I,
// 只有通过这样,方法才能访问外部的变量,否则怎么访问?Lamdha 本质上也只是简化操作而已。// 所以,以上 Lamdha 绑定部分可以等价于下面这样:
I = i;
btn.Click += ButtonClick;
// 而在 ButtonClick 内部的实现则可以是:
MessageBox.Show("Test" + I.ToString());// 很明显,当点击按钮触发事件的时候,取得的是 I 的值。// 而且还有一点,在循环退出去之后,i 还做了一次自增,而这时也确实显示的是 50。
// 我觉得微软内部在实现的方式上对 i 的变量的改变进行了监听。所以当每次 i 的值改变,
// I 的值也会重新复制,总的来说,
// 我们可以用以下替换代码来解释上述原因:
private int I = 0;private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Name = "Button" + i;
btn.Text = (i + 1).ToString();
btn.Location = new Point((i % 3) * btn.Width, (i / 3) * btn.Height);
I = i;
btn.Click += ButtonClick;
panel1.Controls.Add(btn);
} I++;
}
private void ButtonClick(object sender, EventArgs e)
{
MessageBox.Show(I.ToString());
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Test5
{
class Program
{
static void Main(string[] args)
{
for (int i = 0; i < 100; i++)
{
Button button = new Button();
button.Click += (obj, e) =>
{
MessageBox.Show(i.ToString());
};
}
}
}
}
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代码大小 81 (0x51)
.maxstack 4
.locals init ([0] class [System.Windows.Forms]System.Windows.Forms.Button button,
[1] class [mscorlib]System.EventHandler 'CS$<>9__CachedAnonymousMethodDelegate1',
[2] class Test5.Program/'<>c__DisplayClass2' 'CS$<>8__locals3',
[3] bool CS$4$0000)
IL_0000: nop
IL_0001: ldnull
IL_0002: stloc.1
IL_0003: newobj instance void Test5.Program/'<>c__DisplayClass2'::.ctor()
IL_0008: stloc.2
IL_0009: ldloc.2
IL_000a: ldc.i4.0
IL_000b: stfld int32 Test5.Program/'<>c__DisplayClass2'::i
IL_0010: br.s IL_0042
IL_0012: nop
IL_0013: newobj instance void [System.Windows.Forms]System.Windows.Forms.Button::.ctor()
IL_0018: stloc.0
IL_0019: ldloc.0
IL_001a: ldloc.1
IL_001b: brtrue.s IL_002c
IL_001d: ldloc.2
IL_001e: ldftn instance void Test5.Program/'<>c__DisplayClass2'::'<Main>b__0'(object,
class [mscorlib]System.EventArgs)
IL_0024: newobj instance void [mscorlib]System.EventHandler::.ctor(object,
native int)
IL_0029: stloc.1
IL_002a: br.s IL_002c
IL_002c: ldloc.1
IL_002d: callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::add_Click(class [mscorlib]System.EventHandler)
IL_0032: nop
IL_0033: nop
IL_0034: ldloc.2
IL_0035: dup
IL_0036: ldfld int32 Test5.Program/'<>c__DisplayClass2'::i
IL_003b: ldc.i4.1
IL_003c: add
IL_003d: stfld int32 Test5.Program/'<>c__DisplayClass2'::i
IL_0042: ldloc.2
IL_0043: ldfld int32 Test5.Program/'<>c__DisplayClass2'::i
IL_0048: ldc.i4.s 100
IL_004a: clt
IL_004c: stloc.3
IL_004d: ldloc.3
IL_004e: brtrue.s IL_0012
IL_0050: ret
} // end of method Program::Main
lambda新建了一个Test5.Program/'<>c__DisplayClass2',用的是
Test5.Program/'<>c__DisplayClass2'::i