43

To implement a tab-based environment in WPF we need to convert our forms to user controls, however when doing this, the Loaded event of the user control is called two times.

While searching on the internet other people also pointed this issue. How can we ensure that loaded event is called only once? Because when it is called multiple times, initialization of our controls happens multiple times.

Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
Muhammad Akhtar
  • 51,913
  • 37
  • 138
  • 191
  • I tried reproducing this in an empty .NET 4.0 WPF application and the Loaded event only fired once. Have you tried looking at the call stack to see if maybe something weird is going on in the .NET Framework before it fires the Loaded event? – Bob Wintemberg Feb 25 '11 at 23:07
  • 2
    Place your user control inside a tab control, and you'll be able to reproduce the issue when switching tabs. – Eternal21 Apr 10 '13 at 14:49
  • Try using Pages and Frames. It's much simpler and cleaner for grouping controls. – Justanother Okie Aug 13 '18 at 21:15

4 Answers4

51

As explained in this blog, the Loaded event is fired when ever a control is about to be rendered (i.e. added to the visual tree).

There are several controls that would cause your control to be loaded/unloaded multiple times. For example, the native WPF TabControl only renders the content of the selected tab. So when you select a new tab, the content of the previously selected tab is unloaded. If you click back to the previously selected tab, then it's content is reloaded.

One work around is to use a Boolean to flag whether you have already initialized your control, as suggested by others. Alternatively, you may be able to use the Initialized event instead.

CodeNaked
  • 40,753
  • 6
  • 122
  • 148
  • 2
    I'm using TabControl's `ItemsSource` to bind several tabs and use `DataTemplate` to bind ViewModel to the tab views. In my case, not only is the `Loaded` event fired again but also the **constructor** of the tab view is called again. It seems that WPF is re-creating my tab control completely each time I switch the tab. – Felix Mar 30 '17 at 10:44
  • @Felix I'm facing the same issue, any solution? – Luke May 15 '18 at 08:09
  • @Luke This is an issue that we can't change. So I save everything in the ViewModel and let WPF recreate it every time. – Felix May 16 '18 at 02:07
26

Your routed event handler can (and should) remove itself from the Loaded hook as the first thing it does.

public class MyClass : Window
{
    public MyClass()
    {
        Loaded += MyLoadedRoutedEventHandler;
    }

    void MyLoadedRoutedEventHandler(Object sender, RoutedEventArgs e)
    {
        Loaded -= MyLoadedRoutedEventHandler;
        /// ...
    }
};
Glenn Slayden
  • 17,543
  • 3
  • 114
  • 108
  • Well.. your suggestion has certainly saved my sorry ass, Glenn... but can you explain why this removal should take place INSIDE the event handler? Thanks – Richard Hammond Nov 11 '18 at 00:25
  • 6
    @RichardHammond Because, at what earlier opportunity can you positively be assured that the event has indeed successfully fired? Where else would you suggest to put the removal? – Glenn Slayden Nov 11 '18 at 05:13
3

Set a loaded flag in the event, and, if the flag has already been set, don't do anything.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
0

As mentioned above,you can use bool flag for it.

bool isPageLoadingForFirstTime = true;

public void LoadedEvent()
{
  if(ispageLoadingForFirstTime)
   {
      //do something
      ispageLoadingForFirstTime = false;
   }
}
Batuhan Gedik
  • 37
  • 1
  • 8
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 21 '21 at 13:02