Winform中UserControl的Load事件只会触发一次

3
我有一个Winform,其中有一个面板,根据用户的输入加载不同的用户控件。
// to load a user control
pnlContent.Controls.Add(uc1);

// to change to different user control
pnlContent.Controls.Clear();
pnlContent.Controls.Add(uc2);

我注意到的是当我清空 pnlContent 并重新添加 uc1 时,uc1 的 Load 事件不会被触发,也就是说 uc1 的 Load 事件只在第一次添加到 pnlContent 时才会触发。

有没有办法让 Load 事件每次用户控件添加到面板时都触发?如果没有,我的选择是什么?

请给予建议。


在页面初始化时执行此操作。 - Chamika Sandamal
uc1 正在从控件集合中移除。你可以在重新添加它之前使用 uc1 = new YourUserControlType,并在移除时处理它,但这取决于你的设置。你所做的只是将 uc1 重新添加到集合中,而不是重新加载它。 - KreepN
不幸的是,我不能重新“更新”uc1,必须保留它或用户需要重新输入uc1的输入。 - Eddie
页面初始化事件?我在uc1的事件列表中找不到它。 - Eddie
1
@Eddie 如果你想在用户控件的Load事件上执行某些操作,你应该将代码移动到公共方法中,并在需要时调用它。 - King King
显示剩余3条评论
3个回答

6
  pnlContent.Controls.Clear();

你需要非常小心使用这种方法,它并不像你想象的那样工作。它并没有处理面板上的控件,而只是将它们移除。这些控件仍然存在,并被放置在隐藏的“停车窗口”中。它们可以随时被移到另一个父级容器下。
很多情况下,这种移动并没有发生,导致控件会一直泄漏。在你的特定情况下,情况还没有变得那么糟糕,因为你仍然有一个对控件的引用。你的变量uc1存储了它。但后果是,它的Load事件不会再次触发,这只会发生一次。
所以,如果你真的需要Load事件被触发,你应该按照正确的方式处理面板上的控件。
 while (pnlContent.Controls.Count > 0) pnlContents.Controls[0].Dispose();

然后,您需要创建一个实例,无论用户控件类型 uc1 引用的是什么。当您将其添加到面板时,您将触发Load事件。

另一个强烈的隐含信息是,您很可能根本不应该使用Load事件。在绝大多数情况下,Load事件处理程序中的代码都应该放在构造函数中。只有在需要了解Handle属性或需要确保已计算布局以便知道控件的最终大小时,才需要Load事件。这种情况很少见。


Controls.Clear()的解释很好!是的,我不想处理uc1;这就是为什么我调用Clear()。如果我处理了uc1并重新“new”它,用户将不得不重新输入uc1上的所有输入。我正在远离Load事件,并提取逻辑到一个公共方法中,让父/主窗体在将uc1添加到pnlContent后调用它。 - Eddie
@Eddie,我不明白为什么你在Load事件中有一些代码,但你仍然想在你的UserControl已经加载时重新执行它?这根本不合逻辑。 - King King
KingKing和Hans Passant是正确的。我不应该使用Load事件来执行/重新执行我的代码。我已经将代码提取到一个公共方法中,并让父/主窗体在pnlContent.Controls.Add(uc1)之后调用它。 - Eddie
最后一段解决了我的问题! 我实例化了一个控件两次,并将每个控件添加到不同的父控件中,Load方法只被调用了一次。将该代码移到构造函数中修复了我的问题。不确定为什么之前的开发人员决定使用Load。 - styfle

1
我有一个类似工具箱的控件,当用户按下切换按钮时,它会被添加到另一个父控件中并从中移除。
我使用ParentChanged事件而不是Load事件(只在第一次将控件添加到其父控件集合时触发)。然后我检查Parent属性:如果为null,则表示该控件已从其父控件集合中移除。如果不是,则表示该控件刚刚被添加。
private void MyUserControl_ParentChanged(object sender, EventArgs e)
{
    try
    {
        if (this.Parent != null) 
        {
            // Perform initializations
        }
    }
    catch (Exception ex)
    {
        // Do my normal exception handling
    }
}

0

我认为你可以做到:

uc1.load(this, null);

因为你只是移除它,然后再添加回去。你没有重新初始化它。


load是什么类型? - King King
实际上,如果他说“uc1的Load事件没有被触发”,那么我认为他有一个Load事件或类似的东西? 我知道这是一个WinForm应用程序,而我来自asp.net编程,那里总是有onInit等事件。我认为这在Winforms中也是可用的,他在其中执行了一些代码。 - DatRid
无法执行,因为Load是事件处理程序而不是方法。 - Eddie
第二次、第三次、第四次等不会触发。它只在第一次触发,即“pnlContent.Control.Add(uc1)”。 - Eddie
如果您编写一个方法,从Loadevent中调用它,并再次添加您的控件,会怎么样? - DatRid
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接