我正在做一个包含动态控件创建和从WinForm中删除的项目, 所以我决定将这一部分放在一个小型测试项目上。 测试项目有两个文件Form1.cs和NewControls.cs。每当用户单击表单上已有的“添加”按钮时,此程序就会创建其他按钮。单击该按钮时会删除新创建的按钮(自我删除按钮)。删除按钮后,其他按钮的名称,文本及其位置也会根据局部变量(controlIndex)进行更改。
public partial class Form1 : Form
{
static List<NewControl> newControlsList = new List<NewControl>();
public Form1()
{
InitializeComponent();
}
private void Add_Click(object sender, EventArgs e)
{
newControlsList.Add(new NewControl(newControlsList.Count));
}
public static void RemoveButton(object sender, EventArgs e)
{
NewControl tempNewControl = (NewControl)(sender as Button).Tag;
tempNewControl.RemoveControl();
newControlsList.Remove(tempNewControl);
MessageBox.Show("Removed!");
foreach (NewControl tempcontrol in newControlsList)
{
tempcontrol.controlIndex = newControlsList.IndexOf(tempcontrol);
tempcontrol.PlaceControl();
}
}
}
class NewControl
{
public int controlIndex = 0;
Button newButton = new Button();
public NewControl(int index)
{
controlIndex = index;
PlaceControl();
}
public void RemoveControl()
{
newButton.Dispose();
Form1.ActiveForm.Controls.Remove(newButton);
}
public void PlaceControl()
{
newButton.Tag = this;
newButton.Name = "btn" + controlIndex.ToString("D2");
newButton.Text = "btn" + controlIndex.ToString("D2");
newButton.Size = new Size(100, 20);
newButton.Left = controlIndex * 100;
Form1.ActiveForm.Controls.Add(newButton);
newButton.Click += new EventHandler(Form1.RemoveButton);
}
}
程序几乎按预期工作。问题是我在RemoveButton()中的form1.cs中使用的MessageBox多次触发(而不是一次),这意味着整个方法被执行多次。实际上我粘贴了MessageBox进行调试(排序)。
因为我无法像“Form1.ActiveForm.Controls.Add(newButton);”那样调试应用程序。语句执行,调试器抛出NullReferenceException,因为调试时没有活动表单。 我知道这就像一个奖金问题,但我想把它放在那里。我是一个初学者,无法通过这两个问题找到方法。第一个问题对我的原始项目非常重要,因为当添加许多控件时它会引起问题。
答案 0 :(得分:2)
我认为这是因为你从Form1.cs和NewControl类的构造函数中调用PlaceControl,因为你说newButton.Click += new EventHandler(Form1.RemoveButton);
。
您正在添加EventHandlers,因此可以有更多它们
因此,当您多次调用placeControl时,我认为您有多个事件处理程序。
答案 1 :(得分:1)
可能还没有RemoveButton删除EventHandler。 (我最近一直在java工作,所以我的术语对于C#来说可能有些偏差。)建议:当你需要时将控制可见性设置为true,否则设置为false而不是添加和删除。
答案 2 :(得分:1)
每次删除按钮时,您都会检查现有的控件列表,然后调用“PlaceControl”,它会附加另一个处理程序。
foreach (NewControl tempcontrol in newControlsList)
{
tempcontrol.controlIndex = newControlsList.IndexOf(tempcontrol);
tempcontrol.PlaceControl();
}
从RemoveButton
删除上面的代码块,您会看到动态添加的按钮每次只触发一次事件。
答案 3 :(得分:1)
在您的RemoveButton事件中,您循环每个按钮并再次调用PlaceControl 唯一的原因是重新定位其余控件 我认为调用一个只做这项工作的单独方法会更好。
public void RepositionControl()
{
newButton.Left = controlIndex * 100;
}
这样可以防止乱七八糟地添加事件处理程序