C# windows 表单引用控件 - NullReferenceException
C# windows forms reference control - NullReferenceException
谁能解释为什么我在创建新 Button 并尝试引用它时得到 NullReferenceException?创建按钮并指定名称工作正常,但引用它却不行。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DragNDrop_1
{
public partial class Form1 : Form
{
//Variables----------------------------------------------------------------------
int ButtonID = 100;
bool isDraggingButton = false;
public Form1()
{
InitializeComponent();
}
//----------------------------------------------------------------------Variables
private void btn_addButton_Click(object sender, EventArgs e)
{
AddButton();
}
public void AddButton()
{
Button b = new Button();
b.Name = "Button" + ButtonID.ToString();
b.Text = "Button" + ButtonID.ToString();
b.Location = new Point(ButtonID, ButtonID);
ButtonID = ButtonID + 100;
pnl_DragNDrop.Controls.Add(b);
isDraggingButton = true;
}
private void DragTimer_Tick(object sender, EventArgs e)
{
if (isDraggingButton == true)
{
Point mouse = PointToClient(MousePosition);
this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
}
}
}
}
定时器中出现异常,我在其中尝试引用最后创建的按钮。我阅读了一些关于此异常的线程,但我仍然无法发现错误。
是的,我知道这很麻烦,我应该适当地创建一个自定义循环或 de-/re- 激活计时器,但这仅用于测试目的。请注意,我是 C# 和 Windows 表单的新手。
编辑:正如 Lukasz M 所解释的,这是一个关于所有权的问题(也许术语不正确,这是我能想到的最好的德英翻译)。这既不是线程 I "duplicated" 中问题的焦点,也不是答案中提到的。如果是的话,我不得不质疑我的英语水平。不管怎样,我只是想澄清一下,我确实阅读了线程,但无法找到解决方案。也许只是缺乏英语和 C# 技能,但我很确定这不是重复的。
这是因为在 AddButton
方法中您创建了按钮,但没有将其直接添加到表单的控件中,而是添加到 pnl_DragNDrop.Controls
集合中。
你可以尝试改变这个:
this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
对此:
pnl_DragNDrop.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
它应该可以正常工作。
另一种方法是将 b
按钮保存在 class 字段中,而不是方法中的变量。这样,您可以在不同的方法中引用控件,而无需通过 Id
在 Controls
集合中找到它。您可能还想添加多个具有不同 Id
值的按钮,因此存储和引用创建的按钮的具体实现可能取决于实际用例。
更新
为了使代码实际工作,还请注意,在您创建 b
控件之后,您修改了用于组成其名称的变量:
ButtonID = ButtonID + 100;
然后,在DragTimer_Tick
方法中你使用修改后的值重建控件的名称,但它已经不同了,所以找不到控件。
按名称搜索控件时,您可以保存 ButtonID
的先前值或保存用作按钮名称的整个字符串(如评论中所述),以便能够使用它来查找稍后控制。
谁能解释为什么我在创建新 Button 并尝试引用它时得到 NullReferenceException?创建按钮并指定名称工作正常,但引用它却不行。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DragNDrop_1
{
public partial class Form1 : Form
{
//Variables----------------------------------------------------------------------
int ButtonID = 100;
bool isDraggingButton = false;
public Form1()
{
InitializeComponent();
}
//----------------------------------------------------------------------Variables
private void btn_addButton_Click(object sender, EventArgs e)
{
AddButton();
}
public void AddButton()
{
Button b = new Button();
b.Name = "Button" + ButtonID.ToString();
b.Text = "Button" + ButtonID.ToString();
b.Location = new Point(ButtonID, ButtonID);
ButtonID = ButtonID + 100;
pnl_DragNDrop.Controls.Add(b);
isDraggingButton = true;
}
private void DragTimer_Tick(object sender, EventArgs e)
{
if (isDraggingButton == true)
{
Point mouse = PointToClient(MousePosition);
this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
}
}
}
}
定时器中出现异常,我在其中尝试引用最后创建的按钮。我阅读了一些关于此异常的线程,但我仍然无法发现错误。 是的,我知道这很麻烦,我应该适当地创建一个自定义循环或 de-/re- 激活计时器,但这仅用于测试目的。请注意,我是 C# 和 Windows 表单的新手。
编辑:正如 Lukasz M 所解释的,这是一个关于所有权的问题(也许术语不正确,这是我能想到的最好的德英翻译)。这既不是线程 I "duplicated" 中问题的焦点,也不是答案中提到的。如果是的话,我不得不质疑我的英语水平。不管怎样,我只是想澄清一下,我确实阅读了线程,但无法找到解决方案。也许只是缺乏英语和 C# 技能,但我很确定这不是重复的。
这是因为在 AddButton
方法中您创建了按钮,但没有将其直接添加到表单的控件中,而是添加到 pnl_DragNDrop.Controls
集合中。
你可以尝试改变这个:
this.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
对此:
pnl_DragNDrop.Controls["Button" + ButtonID.ToString()].Location = new Point(mouse.X + 20, mouse.Y + 20);
它应该可以正常工作。
另一种方法是将 b
按钮保存在 class 字段中,而不是方法中的变量。这样,您可以在不同的方法中引用控件,而无需通过 Id
在 Controls
集合中找到它。您可能还想添加多个具有不同 Id
值的按钮,因此存储和引用创建的按钮的具体实现可能取决于实际用例。
更新
为了使代码实际工作,还请注意,在您创建 b
控件之后,您修改了用于组成其名称的变量:
ButtonID = ButtonID + 100;
然后,在DragTimer_Tick
方法中你使用修改后的值重建控件的名称,但它已经不同了,所以找不到控件。
按名称搜索控件时,您可以保存 ButtonID
的先前值或保存用作按钮名称的整个字符串(如评论中所述),以便能够使用它来查找稍后控制。