WPF User Control loading twice
Asked Answered
S

5

7

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 is loaded like that, else how to solve this issue.

Soundproof answered 17/3, 2010 at 8:17 Comment(0)
N
9

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

Naga answered 1/4, 2010 at 18:47 Comment(0)
H
8

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 */
}
Haroldson answered 17/11, 2012 at 21:5 Comment(0)
S
5

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

Synecious answered 15/12, 2011 at 11:15 Comment(0)
A
0

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;
}
Anabantid answered 17/6, 2010 at 19:51 Comment(0)
J
-2
    /// <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

Jahdiel answered 12/12, 2020 at 1:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.