海
我有一个WPF用户控件,当我在另一个窗口中使用该控件时它加载两次,所以它为我抛出异常,因为它在usercontrol_loaded事件中有一些功能,当它加载两次抛出错误时,有没有其他方法可以检查如果像这样加载usercontrol,否则如何解决这个问题.
如果你这样做,你不需要"firstLoadCalled"标志:
public MyControl()
{
this.Loaded += MyControl_Loaded;
}
private void MyControl_Loaded(object sender, RoutedEventArgs e)
{
this.Loaded -= MyControl_Loaded; //make it so MyControl_Loaded is only called once
/* code that runs once on first load */
}
Run Code Online (Sandbox Code Playgroud)
长话短说,使用布尔标志:
private bool firstLoad = true;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (firstLoad)
{
firstLoad = false;
// Do somthing that want to do only once...
}
}
Run Code Online (Sandbox Code Playgroud)
更长的故事:显然,在WPF中你不能假设加载的事件只被触发一次.
我在Tabitem中使用用户控件遇到了同样的情况.每次通过选择它激活Tabitem时,将为此tabitem中的所有控件触发加载的事件.
干杯
在给Zane的帖子写评论之后,我想到了一个想法:实际上你不想使用布尔标志这样的解决方案,或者你必须使它更加健壮.
它来了,控制可能会被重新使用.这意味着,可以将控件添加到树中,然后删除,然后添加,然后删除等等.如果您确实需要过滤掉Loaded的多个调用,那么您也必须跟踪Unloaded事件!
按照Zane的例子,它应该类似于以下代码:
using System.Windows;
using System.Windows.Controls;
public class LoadOnceUserControl : UserControl
{
private bool firstLoadCalled = false;
public LoadOnceUserControl()
{
this.Unloaded += (sender,e) => firstLoadCalled = false;
this.Loaded += (sender,e) =>
{
if (this.firstLoadCalled) return;
this.firstLoadCalled = true;
var copy = this.FirstLoaded;
if (copy != null) copy(sender,e);
});
}
/*public*/ event RoutedEventHandler FirstLoaded;
}
Run Code Online (Sandbox Code Playgroud)
请注意,为了对称而添加类似的FirstUnloaded也是合理的.我从来没有看到它被称为虚假.并且记住,尽管我在评论Zane的时候写过 - 在这种方法中你不应该分离那些处理程序