wpf Window.Loaded 和 Window.ContentRendered 事件有什么区别

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18452756/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 23:55:08  来源:igfitidea点击:

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

wpfeventswindow

提问by Tony Vitabile

What's the difference between the Window.Loadedand Window.ContentRenderedevents in WPF? Is the ContentRenderedevent called first?

WPF 中的Window.LoadedWindow.ContentRendered事件有什么区别?ContentRendered事件是第一个调用的吗?

The description of the Window.ContentRenderedevent herejust says

这里Window.ContentRendered事件的描述只是说

Occurs after a window's content has been rendered.

在呈现窗口的内容之后发生。

The description of the Window.Loadedevent heresays

这里Window.Loaded事件的描述说

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

在元素布局、呈现并准备好进行交互时发生。

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

我有一个案例,我想将窗口设置MaxHeight为显示我的窗口的屏幕工作区域的高度。我应该在哪个事件中进行?

Edit:

编辑:

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

我想我找到了我要找的东西,但我现在更困惑了。该Loaded事件首先发生,然后ContentRendered事件发生。在 Chris Sells 和 Ian Griffiths 的 Programming WPF 一书中,它说该Loaded事件是

Raised just before the window is shown

在显示窗口之前引发

While the 'ContentRendered` event is

虽然 'ContentRendered` 事件是

Raised when the window's content is visually rendered.

当窗口的内容在视觉上呈现时引发。

This contradicts what the MSDN documentation says about the Loadedevent:

这与 MSDN 文档对Loaded事件的描述相矛盾:

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

在元素布局、呈现并准备好进行交互时发生。

This is even more confusing now.

这现在更令人困惑了。

回答by Anatoliy Nikolaev

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

我认为这两个事件之间几乎没有区别。为了理解这一点,我创建了一个简单的操作示例:

XAML

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

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 Loadedappears the first after the message ContentRendered. This confirms the information in the documentation.

在这种情况下,消息Loaded出现在消息之后的第一个ContentRendered。这确认了文档中的信息。

In general, in WPF the Loadedevent fires if the element:

通常,在 WPF 中,Loaded如果元素如下,则事件会触发:

is laid out, rendered, and ready for interaction.

已布局、呈现并准备好进行交互。

Since in WPF the Windowis 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 Windowand created an ContentRenderedevent. Remarks from MSDN:

由于在 WPF 中Window是相同的元素,但它通常应该是排列在根面板中的内容(例如:)Grid。因此,要监视的内容Window并创建了一个ContentRendered事件。来自 MSDN 的评论:

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

如果窗口没有内容,则不会引发此事件。

That is, if we create a Window:

也就是说,如果我们创建一个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 Loadedevent.

它只会工作Loaded事件。

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

关于访问 中的元素Window,它们的工作方式相同。让我们创建一个Label在主要GridWindow。在这两种情况下,我们都成功获得了访问权限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 Stylesand Templates, at this stage they are successfully applied, and in these events we will be able to access them.

至于StylesTemplates,在这个阶段它们被成功应用,在这些事件中我们将能够访问它们。

For example, we want to add a Button:

例如,我们要添加一个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 Loadedevent, Buttonto add to Gridimmediately at the appearance of the Window. In the case of ContentRenderedevent, Buttonto add to Gridafter all its content will appear.

在的情况Loaded下,Button添加到Grid立即在的外观Window。在ContentRendered事件的情况下,Button添加到Grid它的所有内容之后都会出现。

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

因此,如果您想在加载之前添加项目或更改,Window您必须使用该Loaded事件。如果要进行与内容相关的操作,Window例如截屏,则需要使用事件ContentRendered

回答by sa_ddam213

If you visit this link https://msdn.microsoft.com/library/ms748948%28v=vs.100%29.aspx#Window_Lifetime_Eventsand scroll down to Window Lifetime Events it will show you the event order.

如果您访问此链接https://msdn.microsoft.com/library/ms748948%28v=vs.100%29.aspx#Window_Lifetime_Events并向下滚动到 Window Lifetime Events,它将显示事件顺序。

Open:

打开:

  1. SourceInitiated
  2. Activated
  3. Loaded
  4. ContentRendered
  1. 源启动
  2. 活性
  3. 已加载
  4. 内容渲染

Close:

关闭:

  1. Closing
  2. Deactivated
  3. Closed
  1. 关闭
  2. 停用
  3. 关闭

回答by Trevy Burgess

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

如果您使用数据绑定,则需要使用 ContentRendered 事件。

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.

对于下面的代码,当引发 Loaded 事件时,Header 为 NULL。但是,当引发 ContentRendered 事件时,Header 获取其值。

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

回答by marsh-wiggle

This is not about the difference between Window.ContentRenderedand Window.Loadedbut about what how the Window.Loadedevent can be used:

这不是关于 和 之间的区别Window.ContentRenderedWindow.Loaded而是关于如何使用Window.Loaded事件:

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
    }