WPF用户控件加载两次

时间:2010-03-17 08:17:22

标签: wpf user-controls

Hai

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

5 个答案:

答案 0 :(得分: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 */
}

答案 1 :(得分: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...
        }
    }

更长的故事: 显然,在WPF中,您不能假设加载的事件只被触发一次。

我在Tabitem中使用用户控件遇到了同样的情况。 每次通过选择激活Tabitem时,都会为此tabitem中的所有控件触发加载的事件。

干杯

答案 2 :(得分:5)

在给Zane的帖子写评论之后,我想到了一个想法:实际上你不想使用布尔标志这样的解决方案,或者你必须使它更加健壮。

原来,控制可能会被重新使用。这意味着,可以将控件添加到树中,然后删除,然后添加,然后删除等等。如果您确实需要过滤掉Loaded的多次调用,那么必须跟踪已卸载事件!

按照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;
}

请注意,为了对称而添加类似的FirstUnloaded也是合理的。我从来没有看到它被称为虚假。 请注意,尽管我在评论Zane的时候写过 - 在这种方法中你不应该分离那些处理程序

答案 3 :(得分:0)

是的,我发现这种行为真的很奇怪。最终我认为Hertzel所说的是最好的方式 - 或者像这样推导出一个新的UserControl类:

你可以从LoadOnceUserControl派生东西,它的FirstLoaded事件只会被调用一次。

using System.Windows;
using System.Windows.Controls;
public class LoadOnceUserControl : UserControl
{
    private bool firstLoadCalled = false;

    public LoadOnceUserControl()
    {
        // Hook up our loaded event
        this.Loaded += new RoutedEvent(delegate(object sender, RoutedEventArgs e)
        {
            // If FirstLoad hasn't been called and there are events to be called...
            if (!this.firstLoadCalled && this.FirstLoaded != null)
            {
                this.FirstLoaded(sender, e);
            }

            // We've already called (or attempted to call) FirstLoad.
            this.firstLoadCalled = true;
        });
    }

    event RoutedEventHandler FirstLoaded;
}

答案 4 :(得分:-1)

    /// <summary>
    /// Interaction logic for HTMLViewer.xaml
    /// <br/>
    /// 20201208
    /// </summary>
    public partial class FoldersHistory : UserControl, ViewDocument_I, ViewNavigate_I
    {

        public FoldersHistory()
        {
            InitializeComponent();
            //
            Loaded += Control_Loaded;
            Unloaded += Control_Unloaded;
        }

        private bool LOADED = false;
        void Control_Loaded(object sender, RoutedEventArgs e)
        {
            if (LOADED)
                return;
            LOADED = true;

            // *** DO YOUR PROCESS ***

enter image description here