44

I am listening for the loaded event of a Page. That event fires first and then all the children fire their load event. I need an event that fires when ALL the children have loaded. Does that exist?

Shaun Bowe
  • 9,840
  • 11
  • 50
  • 71

7 Answers7

63

I hear you. I also am missing an out of the box solution in WPF for this.

Sometimes you want some code to be executed after all the child controls are loaded.

Put this in the constructor of the parent control

Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => {code that should be executed after all children are loaded} ));

Helped me a few times till now.

buckley
  • 13,690
  • 3
  • 53
  • 61
12

Loaded is the event that fires after all children have been Initialized. There is no AfterLoad event as far as I know. If you can, move the children's logic to the Initialized event, and then Loaded will occur after they have all been initialized.

See MSDN - Object Lifetime Events.

configurator
  • 40,828
  • 14
  • 81
  • 115
3

You can also use the event: ContentRendered.

http://msdn.microsoft.com/en-us/library/ms748948.aspx#Window_Lifetime_Events

Bert-jan
  • 21
  • 6
Rover
  • 2,203
  • 3
  • 24
  • 44
0

One of the options (when content rendered):

this.LayoutUpdated += OnLayoutUpdated;

private void OnLayoutUpdated(object sender, EventArgs e)
            {
                if (!isInitialized && this.ActualWidth != 0 && this.ActualHeight != 0)
                {
                    isInitialized = true;
                    // Logic here
                }
            };
Ievgen
  • 4,261
  • 7
  • 75
  • 124
0

WPF cant provide that kind of an event since most of the time Data is determining whther to load a particular child to the VisualTree or not (for example UI elements inside a DataTemplate)

So if you can explain your scenario little more clearly we can find a solution specific to that.

Jobi Joy
  • 49,102
  • 20
  • 108
  • 119
0

Put inside your xaml component you want to wait for, a load event Loaded="MyControl_Loaded" like

<Grid Name="Main" Loaded="Grid_Loaded"...>
<TabControl Loaded="TabControl_Loaded"...>
<MyControl Loaded="MyControl_Loaded"...>
...

and in your code

bool isLoaded;

private void MyControl_Loaded(object sender, RoutedEventArgs e)
{
   isLoaded = true;
}

Then, inside the Event triggers that have to do something but were triggering before having all components properly loaded, put if(!isLoaded) return; like

private void OnButtonChanged(object sender, RoutedEventArgs e)
{
    if(!isLoaded) return;

    ... // code that must execute on trigger BUT after load
}
Paul Efford
  • 261
  • 4
  • 12
-2

I ended up doing something along these lines.. your milage may vary.

void WaitForTheKids(Action OnLoaded)
{
  // After your children have been added just wait for the Loaded
  // event to fire for all of them, then call the OnLoaded delegate

  foreach (ContentControl child in Canvas.Children)
  {
    child.Tag = OnLoaded; // Called after children have loaded
    child.Loaded += new RoutedEventHandler(child_Loaded);
  }
}
internal void child_Loaded(object sender, RoutedEventArgs e)
{
  var cc = sender as ContentControl;
  cc.Loaded -= new RoutedEventHandler(child_Loaded);

  foreach (ContentControl ctl in Canvas.Children)
  {
    if (!ctl.IsLoaded)
    {
      return;
    }
  }
  ((Action)cc.Tag)();
}
Weezelboy
  • 117
  • 1
  • 2
  • 8