这真的是我编程生活中最烦人的事情:
我有一个与我的申请一起保存的表格。我没有调用某些方法来处理它的代码,我不希望它以任何理由被处理,我确定如果它发生,原因不会在我的代码中。这个表单是一个自定义表单,它有一个名为 Next() 的方法,这个 Next() 只是在表单上显示下一个项目信息。
当我按下一个导致调用 Next() 的按钮时发生了最糟糕的事情,并且出现了一个异常说“对象引用未设置为对象的实例”。什么?这是代码,我将表单的引用保存到名为“currentShownForm”的表单变量中(一次只显示我的表单之一,所有这些都应该与我的应用程序一起使用):
private void ShowForm(CustomRibbonForm form) { if (!form.Visible) { if (currentShownForm != null) currentShownForm.Hide(); form.Show(); currentShownForm = form; } }
如果我按下 Next 按钮,Next() 会像这样调用:
currentShownForm.Next();
谜团的形式是.Show(); 有了上面的ShowForm()方法,你觉得currentShowForm可以为null吗???什么?任何情况?它为 null 的唯一时刻是在显示第一个表单之前。在第一个显示后,它将是第一个表单,任何其他显示的下一个表单都将被它引用。那么在某些情况下它是如何变为空的???ShowForm() 方法中的代码是我项目中唯一可以更改 currentShownForm 引用的代码。
这真的让我很困惑,我无法相信我所看到的。哦,我的上帝,我对此一无所知,任何想法,但我不得不尝试这样最荒谬的事情:
private void ShowForm(CustomRibbonForm form){
if (!form.Visible)
{
if (currentShownForm != null) currentShownForm.Hide();
currentShownForm = form;
form.Show();
}
}
哇,在尝试这个之前,我不认为它可以让任何事情变得不同,但它确实有效。当我按下 Next 按钮时,currentShownForm 不为空。ShowForm中两行代码的交换有什么魔力???我认为只有一个原因,form.Show() 以某种方式处理了表单本身?但为什么它仍然显示?
值得注意的是我的表单不是 .NET 表单(只是继承自 .NET 表单),它是一个自定义表单,而且它再次来自 DotNetBar lib,哇,我有一个想法,关于写一本你应该写的最烦人的事情知道使用 DotNetBar 时(至少,我有大约 5 件事要写,我敢打赌,如果我仍然使用它,还会有更多)。
请查看上面的代码,并解释一下为什么会发生这种情况?我无法解释它,事实上,我想这是一个错误。
您的帮助将不胜感激!
谢谢!
更新
现在,至少我知道问题发生的原始原因,但仍然不明白为什么:
实际上我的表单有一些自定义控件,这里涉及到的控件是一个CustomComboBox。这个组合框是一个二合一控件,由一个普通的组合框(同样,一个 DotNetBar 组合框,即 ComboBoxEx)和一个可聚焦的标签(一个自定义的用户控件)组成。所有控件都注册一个 ParentChanged 事件来为其父窗体注册一些事件,如下所示:
protected override void OnParentChanged(EventArgs e){
if(Parent is CustomRibbonForm){
((CustomRibbonForm)Parent).RefreshControls += (s,ev) => {
Show();
Hide();
};
}
}
我的表单有一个名为 RefreshControls 的已定义事件,将在需要时引发。它有一个引发该事件的公共方法,称为 RefreshAllControls。并且对该方法的调用放置在 ShowForm() 之后我的主表单(不是我正在谈论的表单)的 Activated 事件处理程序中,如下所示:
Activated += (s,e) => {
ShowForm(myForm);
myForm.RefreshAllControls();
};
接下来是:当我注释掉 Show(); 和隐藏();在 OnParentChanged 方法中,它在两种情况下都可以正常工作:
protected override void OnParentChanged(EventArgs e){
if(Parent is CustomRibbonForm){
((CustomRibbonForm)Parent).RefreshControls += (s,ev) => {
//Show();
//Hide();
};
}
}
但如果不是,则只有 1 个案例有效(在调用 form.Show() 之前分配了 currentShowForm。它更接近问题的原因,但仍然不容易理解。
希望您能通过这次更新向我解释一些事情!谢谢
下一个更新
现在我知道 currentShownForm 为空,因为第一个分配实际上从未完成,显示了表单currentShownForm = form
但未执行,并且因为 currentShownForm 最初为空,在调用 ShowForm() 方法后它仍然为空。
它非常接近原因,但仍然很奇怪:
private void ShowForm(CustomRibbonForm form){
if (!form.Visible)
{
if (currentShownForm != null) currentShownForm.Hide();
form.Show(); //<------ I marked a break point here.
currentShownForm = form; //<----- I also marked a break point here.
}
}
用同样的方法标出两个连续的断点后,似乎可以确定所有的断点都会被单步通过,但只有第一个断点被单步通过。之后显示主界面,绕过第二个断点?????????什么??????????????在调用 form.Show() 之后发生了许多事件,其中大多数是我的自定义控件中的事件(与 Focus、LostFocus 和 Paint 事件有关)。这是我第一次看到如此奇怪的代码步进。现在这很接近事业,希望你有话要说。谢谢