【发布时间】:2016-02-15 20:18:38
【问题描述】:
当用户单击当前位于面板 (UserControl1) 中的 UserControl 上的按钮时,我想将 UserControl (UserControl2) 添加到另一个表单 (MainForm) 的面板中。单击此按钮时,UserControl2 应替换 UserControl1 作为面板的内容。
我已经尝试弄清楚如何使用事件在 UserControl1 和 MainForm 之间进行通信,但我只是不知道从哪里开始,因为我找不到一个可以轻松适应我的示例特殊情况(向面板添加控件)。
THIS 问题类似,但不太适合我想要做的事情(或者至少我不知道如何让它适应我想要做的事情)
我试过这个方法,没有报错,但是我的按钮什么也没做:
主窗体:
private void SubscribeToEvent(MyUserControl1 Button_Click)
{
MyUserControl1 CurrentClass = new MyUserControl1();
CurrentClass.Button.Click += new EventHandler(this.ButtonClickHandler);
}
private void ButtonClickHandler(object sender, EventArgs e)
{
MyUserControl2 MainPanelControls = new MyUserControl2();
MainPanel.SuspendLayout();
MainPanel.Controls.Clear();
MainPanel.Controls.Add(MainPanelControls);
MainPanel.ResumeLayout();
}
用户控制1:
public void Button_Click(object sender, EventArgs e)
{
//... Not sure what I'm missing here
}
我也尝试过这种方法,这次尝试实现类似于我的问题顶部附近的链接中描述的方法。我知道这些显然是错误的(否则我不需要问这个问题),但我没有足够的知识来自己解决这个问题:
用户控制1:
public MyUserControl1()
{
InitializeComponent();
}
private MainForm mainForm = null;
public MyUserControl1(Form callingForm)
{
mainForm = callingForm as MainForm;
InitializeComponent();
}
//...
private void Button_Click(object sender, EventArgs e)
{
MyUserControl2 MainPanelControls = new MyUserControl2();
mainForm.MainPanel.SuspendLayout();
mainForm.MainPanel.Controls.Clear();
mainForm.MainPanel.Controls.Add(MainPanelControls);
mainForm.MainPanel.ResumeLayout();
}
现在,当我单击Button 时,我在mainForm.MainPanel.SuspendLayout(); 处收到"Object reference not set to an instance of an object" 错误(或任何过去的错误)。
我也尝试过修改 Joh 的答案,但最终得到了相同的空引用异常,这次是在 ButtonClickedToMainForm(this, e); 的 Button_Click 事件中,我不确定是否需要创建 ButtonClickedToMainForm 的实例,或者如何正确地做到这一点(如果不是别的,那就是)。
我有一种感觉,我可能只是将其中一些代码放在了错误的位置,所以我希望更有经验的人可以帮助我解决这个问题。
更新
这是我实施 Joh 答案的尝试,对此我太陌生了,我不太确定我在哪里搞砸了:
主窗体:
namespace MyProject
{
public delegate void ButtonClickToMainForm(object sender, EventArgs e);
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
UserControl1 userControl1 = new UserControl1();
userControl1.Button1Clicked += userControl1_Button1Clicked;
}
private void userControl1_Button1Clicked(object sender, EventArgs e)
{
try
{
UserControl2 MainPanelControls = new UserControl2();
MainPanel.SuspendLayout();
MainPanel.Controls.Clear();
MainPanel.Controls.Add(MainPanelControls);
MainPanel.ResumeLayout();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
用户控制1:
public partial class UserControl1: UserControl
{
public event ButtonClickToMainForm Button1Clicked;
public UserControl1()
{
InitializeComponent();
}
private void OnButton1Clicked(object sender, EventArgs e)
{
Button1Clicked?.Invoke(this, e);
}
private void Button1_Click(object sender, EventArgs e)
{
Button1Clicked(this, e); //"Object reference not set to an instance of an object."
}
}
我确定这是我在 UserControl1 上缺少的一些简单的东西,我只是不确定是什么。
【问题讨论】:
-
有关组件间通信的 Winforms 惯用语的详细信息,请参阅标记的副本(
UserControl和Form子类在这里工作相同)。首先,您应该考虑使用事件,以避免耦合组件的实现。如果您在查看相关信息(包括但不限于标记的重复信息)后仍然遇到问题,请提供一个很好的问题minimal reproducible example,清楚地显示您尝试过的内容,以及有关该代码的作用和方式的准确信息这与您想要的不同。 -
抱歉,我认为这样做可能有点过头了。我阅读了描述如何使用事件来处理表单之间通信的答案中的副本,但我根本无法理解。我什至不确定从哪里开始才能将其实施到我的项目中。我想我会继续寻找其他地方。还是谢谢。
-
我已经编辑了我的问题,并提供了有关我遇到的问题的更多信息。
-
@PeterDuniho 有没有办法让它不被标记为重复?我已经浏览了链接的问题,但无法找到一种方法来调整其中发布的任何内容以适应我的特定问题。我看不到使用字符串完成我需要的方法,这似乎是您链接的所有答案的基础。谢谢。
-
第一:虽然汉斯被列在修订历史中,但我不确定这是否算作“编辑”了帖子;因此,他可能会或可能不会通过 @ 语法在此处收到带有评论的通知(您必须找到他撰写、编辑或评论过的帖子)。第二:你并没有真正编辑你的问题,只是在一件接一件的事情上添加。如果你编辑它,你会更成功地让别人认真对待这个问题,重新设计它,使它有一个单一的、简单的代码示例,一个措辞准确的问题,考虑到你的所有进展已经做到了这一点。
标签: c# events controls panel subscribe