0

想象以下场景:

this.SetStyle(ControlStyles.UserPaint, true); //this doesn’t change anything

…

void OpenSomeForm()
{
    SomeForm sf = new SomeForm();
    sf.SomeEvent += new … (SomeEventOcurred);
    sf.ShowDialog();
}

private void SomeEventOcurred(…)
{
    OnePanelInThisForm.Invalidate();
}

private void OnePanelInThisForm_Paint(object sender, PaintEventArgs e)
{
     DoSomeDrawing(e.Graphics);
}

现在,OnePanelInThisForm 在表单加载时正确绘制。但如果 SomeEventOcurred 是从“SomeForm”触发的,则不会触发绘制事件。如果我关闭并重新打开表单,它会正确重绘。如果我在执行的表单中添加一个按钮: OnePanelInThisForm.Invalidate(); 面板正确重绘。

我错过了什么?

更新:澄清。(我们为什么不首先这样做……)

我有一个 FORM_A。这个 FORM_A 有一个面板,它覆盖了 Paint 事件。这是一个标准的 WinForm。在 Paint 中它画了一个圆圈。这行得通。原来 FORM_A 有一个打开 FORM_B 的按钮。但在此之前,它订阅了 FORM_B 中的一个自定义事件,称为:SomeEvent。(参见上面的示例)。所以 FORM_B 可以告诉 FORM_A 关于“SomeEvent”。

现在,FORM_B 也是一个普通的 WinForm。它有一个普通的按钮。在该按钮的 Click 事件中,它会打开 FORM_C。FORM_C 也有一个名为 SomeEvent 的事件,显然 FORM_B 订阅了该事件。和以前一模一样。这个想法是 FORM_C 有一个按钮可以触发该事件,通知感兴趣的订阅者。在这种情况下,当 FORM_C 触发事件时,FORM_B 被订阅并感兴趣。

当 FORM_B 收到回调时,它唯一要做的就是……通知相关方(在本例中为 FORM A)该事件已被触发。

现在,即使 Form C 仍然是顶层表单,调用堆栈也会返回到 FormA,返回到定义为第一个事件的回调的方法。

此代码执行。它所做的只是 somePanel.Invalidate()(或 Refresh(),结果相同)。

该面板的 PAINT 方法中的断点表明代码没有被调用。尽管无效,但没有引发 Paint 事件。我认为发生这种情况是因为表单(以及面板)实际上被 FORMB 和 FORMC(仍然打开)覆盖。

就这样。如果我关闭表格 C 然后关闭表格 B,表格 A 仍然不会引发绘制事件。我已经尝试使表单激活面板无效,但这并没有发生。

如果我关闭表单 A 并重新打开它,那么绘图当然是正确的。

希望这能让它更清楚。

代码并不多,因为这很简单,FORM A > B > C(火灾事件)-> B -> A -> Invalidate()。

4

1 回答 1

1

尝试使用 Refresh() 而不是 Invalidate()。无论如何,这似乎对我来说更有效。

于 2010-05-06T13:29:14.747 回答