【问题标题】:WPF 用户控件的 Loaded 事件多次触发
【发布时间】:2011-03-26 04:17:33
【问题描述】:

要在 WPF 中实现基于选项卡的环境,我们需要将表单转换为用户控件,但是这样做时,用户控件的 Loaded 事件会被调用两次 .

在互联网上搜索时,其他人也指出了这个问题。我们如何确保加载的事件只被调用一次?因为当它被多次调用时,我们控件的初始化会发生多次。

【问题讨论】:

  • 我尝试在一个空的 .NET 4.0 WPF 应用程序中重现它,并且 Loaded 事件只触发了一次。在触发 Loaded 事件之前,您是否尝试过查看调用堆栈以查看 .NET Framework 中是否发生了一些奇怪的事情?
  • 将您的用户控件放在选项卡控件中,您将能够在切换选项卡时重现该问题。
  • 尝试使用页面和框架。对控件进行分组要简单得多。

标签: c# wpf user-controls


【解决方案1】:

如上所述,您可以使用 bool 标志。

bool isPageLoadingForFirstTime = true;

public void LoadedEvent()
{
  if(ispageLoadingForFirstTime)
   {
      //do something
      ispageLoadingForFirstTime = false;
   }
}

【讨论】:

  • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
【解决方案2】:

您的路由事件处理程序可以(并且应该)将自己从 Loaded 挂钩中移除,这是它所做的第一件事。

public class MyClass : Window
{
    public MyClass()
    {
        Loaded += MyLoadedRoutedEventHandler;
    }

    void MyLoadedRoutedEventHandler(Object sender, RoutedEventArgs e)
    {
        Loaded -= MyLoadedRoutedEventHandler;
        /// ...
    }
};

【讨论】:

  • 嗯.. 你的建议确实拯救了我的遗憾,格伦......但是你能解释一下为什么这个删除应该发生在事件处理程序内部吗?谢谢
  • @RichardHammond 因为,在什么更早的机会您可以肯定地确定该事件确实已成功触发?您还建议在哪里删除?
【解决方案3】:

正如blog 中所解释的,当即将呈现控件(即添加到可视化树)时会触发 Loaded 事件。

有几个控件会导致您的控件被多次加载/卸载。例如,原生 WPF TabControl 仅呈现所选选项卡的内容。因此,当您选择新选项卡时,会卸载先前选择的选项卡的内容。如果您单击返回到先前选择的选项卡,则会重新加载其内容。

一种解决方法是使用布尔值来标记您是否已经按照其他人的建议初始化了控件。或者,您可以改用Initialized 事件。

【讨论】:

  • 我正在使用 TabControl 的 ItemsSource 绑定多个选项卡并使用 DataTemplate 将 ViewModel 绑定到选项卡视图。在我的例子中,不仅Loaded 事件再次被触发,而且标签视图的 constructor 也被再次调用。每次切换选项卡时,WPF 似乎都在完全重新创建我的选项卡控件。
  • @Felix 我也遇到了同样的问题,有什么解决办法吗?
  • @Luke 这是我们无法改变的问题。因此,我将所有内容都保存在 ViewModel 中,并让 WPF 每次都重新创建它。
【解决方案4】:

在事件中设置loaded 标志,如果标志已经设置,则不要执行任何操作。

【讨论】:

  • 感谢您的建议,这真的是一个真正的问题,并且由于标签而被调用了两次加载事件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
相关资源
最近更新 更多