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?
7 Answers
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.

- 13,690
- 3
- 53
- 61
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.

- 40,828
- 14
- 81
- 115
-
This does not work if the parent needs to get the exact child's rendered size. – Hrvoje Batrnek Oct 11 '20 at 22:08
You can also use the event: ContentRendered.
http://msdn.microsoft.com/en-us/library/ms748948.aspx#Window_Lifetime_Events
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
}
};

- 4,261
- 7
- 75
- 124
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.

- 49,102
- 20
- 108
- 119
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
}

- 261
- 4
- 12
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)();
}

- 117
- 1
- 2
- 8