开发者

WPF User Control loading twice

Hai

am having a WPF user control, when i use that control in another window it loading twice, so its throwing exception for me, coz am having some function in usercontrol_loaded event, when it loading twice it throwing error, is there any other way to check if the usercontrol 开发者_如何学Gois loaded like that, else how to solve this issue.


Long story short, use a boolean flag:

    private bool firstLoad = true;
    private void UserControl_Loaded(object sender, RoutedEventArgs e)
    {
        if (firstLoad)
        {
            firstLoad = false;

            // Do somthing that want to do only once...
        }
    }

Longer story: Apparently, in WPF you can't assume the loaded event is fired only once.

I've encountered the same situation using a user control in a Tabitem. Every time you activate a Tabitem by selecting it the loaded event is fired for all controls within this tabitem.

Cheers


You don't need a "firstLoadCalled" flag if you do it this way:

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 */
}


After writing comment to Zane's post, a after thought came to me: actually you dont want to use such solution with boolean flag, or you must make it even more robust.

It cames to be, that a Control may be REUSED. This means, that the control may be added to tree, then removed, then added, then removed and so on. If you really need to filter out the multiple invocations of Loaded, you must track the Unloaded event, too!

Following Zane's example, it should resemble following code:

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

Please note that it also could be reasonable to add analogous FirstUnloaded just for symmetry. I have never seen it called spuriously though. And mind that despite waht I wrote in comment to Zane's - in this approach you should not detach that handlers


Yeah, I find this behavior really weird. Ultimately I think that what Hertzel said is the best way to go- that or deriving a new UserControl class like so:

You can derive stuff from LoadOnceUserControl and its FirstLoaded event will be called only once.

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


    /// <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 ***

WPF User Control loading twice

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜