67

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.

Tony Vitabile
  • 8,298
  • 15
  • 67
  • 123

5 Answers5

75

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.

Kay Zed
  • 1,304
  • 2
  • 21
  • 31
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
  • 1
    It would be interested to see what events are raised when the window redraws, for example, minimize the window and then restore it. Is the window's `Loaded` event raised again? Is the `ContentRendered` the only one raised? – Tony Vitabile Aug 27 '13 at 14:34
  • 1
    @Tony Vitabile: Yes, these events will work once, at the start of the `Window` (minimizing and restore not affect). Usually, `Loaded` fires a second time an item is physically removed from the logical tree, and introduced again, then it will fires. – Anatoliy Nikolaev Aug 27 '13 at 14:46
  • 1
    I've been testing this and it's my experience that the `Loaded` event fires before the window is rendered, while the `ContentRendered` event fires after it has been rendered. Interestingly, when `Loaded` fires, the layout & measure passes seem to be complete as `ActualHeight` and `ActualWidth` are set. The window just hasn't been drawn yet. – Tony Vitabile Aug 27 '13 at 20:12
  • @Tony Vitabile: Yes it is possible. My answer to you is not suitable? If you have any questions about the answer, please ask, because I might miss something. – Anatoliy Nikolaev Aug 28 '13 at 04:20
  • 1
    The behavior is the behavior. I'm just trying to make sure I understand what's going on so I can put code in the right places. Thank you, you've helped a lot. – Tony Vitabile Aug 28 '13 at 14:15
  • For those coming here with ContextRendered firing to early: You might consider waiting for LayoutUpdated – Athanviel Jul 13 '21 at 14:35
  • Maybe I'm nitpicking, but accessing Width doesn't prove much, ActualWidth would interest me more to know that layout was actually done. – jv42 Jan 05 '22 at 14:17
55

If you visit this link https://learn.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
John Cummings
  • 1,949
  • 3
  • 22
  • 38
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • Thanks for this info, its a old one but fixed quite a few problems that I was having with WPF and multi threads :D – Camadas Nov 29 '18 at 11:31
14

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}" />
Trevy Burgess
  • 499
  • 5
  • 12
  • 1
    This is the important difference. The binding is done. So registiering to handlers like textchanged, checkboxchanged get fired when you register in Loaded event. But already have been fired once when you register in ContentRendered. – Felix Keil Sep 17 '18 at 09:04
  • From what I understand the Bindings should have been evaluated when the Loaded event is fired. Have you checked the value of the Header on the Loaded raised by MenuItem or the parent Window? The loaded event gets fired from the top-down - Window first and then elements inside it https://learn.microsoft.com/en-us/archive/blogs/mikehillberg/the-loaded-event-and-the-initialized-event – Vivek Rathod Feb 03 '23 at 14:26
1

Window class inheritance

  • Object
  • DispatcherObject
  • DependencyObject
  • Visual
  • UIElement
  • FrameworkElement <- this is where Loaded lives
  • Control
  • ContentControl
  • Window <- this is where ContentRendered lives

The difference is that Loaded fires when the Window (as a FrameworkElement object) itself is ready However, a Window (by itself) is just a title-bar with minimize and maximize buttons, and a big empty space in the middle...

The big empty space is a ContentControl, so after the Window is Loaded and ready, we then turn our attention to the "important" bit, the Window's Content.

Once the Window's Content is rendered onto the screen, then ContentRendered fires.

NOTE: If the window has no content, the ContentRendered event is not fired.

-2

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
    }
marsh-wiggle
  • 2,508
  • 3
  • 35
  • 52