What's the difference between the Window.Loaded and Window.ContentRendered events

WpfEventsWindow

Wpf Problem Overview


What's the difference between the Window.Loaded and Window.ContentRendered events in WPF? Is the ContentRendered event called first?

The description of the Window.ContentRendered event here just says

> Occurs after a window's content has been rendered.

The description of the Window.Loaded event here says

> Occurs when the element is laid out, rendered, and ready for interaction.

I have a case where I want to set the window's MaxHeight to the height of the working area of the screen that is displaying my window. Which event should I do it in?

Edit:

I think I found what I was looking for, but I'm even more confused now. The Loaded event happens first and then the ContentRendered event happens. In the book Programming WPF by Chris Sells & Ian Griffiths, it says that the Loaded event is

> Raised just before the window is shown

While the 'ContentRendered` event is

> Raised when the window's content is visually rendered.

This contradicts what the MSDN documentation says about the Loaded event:

> Occurs when the element is laid out, rendered, and ready for interaction.

This is even more confusing now.

Wpf Solutions


Solution 1 - Wpf

I think there is little difference between the two events. To understand this, I created a simple example to manipulation:

XAML

<Window x:Class="LoadedAndContentRendered.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Name="MyWindow"
        Title="MainWindow" Height="1000" Width="525"
        WindowStartupLocation="CenterScreen"
        ContentRendered="Window_ContentRendered"     
        Loaded="Window_Loaded">

    <Grid Name="RootGrid">        
    </Grid>
</Window>

Code behind

private void Window_ContentRendered(object sender, EventArgs e)
{
    MessageBox.Show("ContentRendered");
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Loaded");
}	

In this case the message Loaded appears the first after the message ContentRendered. This confirms the information in the documentation.

In general, in WPF the Loaded event fires if the element:

> is laid out, rendered, and ready for interaction.

Since in WPF the Window is the same element, but it should be generally content that is arranged in a root panel (for example: Grid). Therefore, to monitor the content of the Window and created an ContentRendered event. Remarks from MSDN:

> If the window has no content, this event is not raised.

That is, if we create a Window:

<Window x:Class="LoadedAndContentRendered.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Name="MyWindow"        
    ContentRendered="Window_ContentRendered" 
    Loaded="Window_Loaded" />
	

It will only works Loaded event.

With regard to access to the elements in the Window, they work the same way. Let's create a Label in the main Grid of Window. In both cases we have successfully received access to Width:

private void Window_ContentRendered(object sender, EventArgs e)
{
    MessageBox.Show("ContentRendered: " + SampleLabel.Width.ToString());
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Loaded: " + SampleLabel.Width.ToString());
}	

As for the Styles and Templates, at this stage they are successfully applied, and in these events we will be able to access them.

For example, we want to add a Button:

private void Window_ContentRendered(object sender, EventArgs e)
{
    MessageBox.Show("ContentRendered: " + SampleLabel.Width.ToString());

    Button b1 = new Button();
    b1.Content = "ContentRendered Button";
    RootGrid.Children.Add(b1);
    b1.Height = 25;
    b1.Width = 200;
    b1.HorizontalAlignment = HorizontalAlignment.Right;
}

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    MessageBox.Show("Loaded: " + SampleLabel.Width.ToString());

    Button b1 = new Button();
    b1.Content = "Loaded Button";
    RootGrid.Children.Add(b1);
    b1.Height = 25;
    b1.Width = 200;
    b1.HorizontalAlignment = HorizontalAlignment.Left;
}

In the case of Loaded event, Button to add to Grid immediately at the appearance of the Window. In the case of ContentRendered event, Button to add to Grid after all its content will appear.

Therefore, if you want to add items or changes before load Window you must use the Loaded event. If you want to do the operations associated with the content of Window such as taking screenshots you will need to use an event ContentRendered.

Solution 2 - Wpf

If you visit this link https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms748948(v=vs.100)#window-lifetime-events and scroll down to Window Lifetime Events it will show you the event order.

Open:

  1. SourceInitiated
  2. Activated
  3. Loaded
  4. ContentRendered

Close:

  1. Closing
  2. Deactivated
  3. Closed

Solution 3 - Wpf

If you're using data binding, then you need to use the ContentRendered event.

For the code below, the Header is NULL when the Loaded event is raised. However, Header gets its value when the ContentRendered event is raised.

<MenuItem Header="{Binding NewGame_Name}" Command="{Binding NewGameCommand}" />

Solution 4 - Wpf

This is not about the difference between Window.ContentRendered and Window.Loaded but about what how the Window.Loaded event can be used:

I use it to avoid splash screens in all applications which need a long time to come up.

    // initializing my main window
    public MyAppMainWindow()
    {
		InitializeComponent();

        // Set the event
		this.ContentRendered += MyAppMainWindow_ContentRendered;
    }

    private void MyAppMainWindow_ContentRendered(object sender, EventArgs e)
    {
		// ... comes up quick when the controls are loaded and rendered
		
        // unset the event
        this.ContentRendered -= MyAppMainWindow_ContentRendered;
		
		// ... make the time comsuming init stuff here
	}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTony VitabileView Question on Stackoverflow
Solution 1 - WpfAnatoliy NikolaevView Answer on Stackoverflow
Solution 2 - Wpfsa_ddam213View Answer on Stackoverflow
Solution 3 - WpfTrevy BurgessView Answer on Stackoverflow
Solution 4 - Wpfmarsh-wiggleView Answer on Stackoverflow