WPF用户控件加载两次

Spe*_*n D 5 wpf user-controls

我有一个WPF用户控件,当我在另一个窗口中使用该控件时它加载两次,所以它为我抛出异常,因为它在usercontrol_loaded事件中有一些功能,当它加载两次抛出错误时,有没有其他方法可以检查如果像这样加载usercontrol,否则如何解决这个问题.

Foc*_*olf 8

如果你这样做,你不需要"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)


Her*_*ess 7

长话短说,使用布尔标志:

    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中的所有控件触发加载的事件.

干杯


que*_*atl 5

在给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的时候写过 - 在这种方法中你不应该分离那些处理程序