60

WPF中的事件Window.Loaded和事件有什么区别?事件是先调用Window.ContentRendered的吗?ContentRendered

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

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

这里Window.Loaded事件描述说

当元素布局、渲染并准备好交互时发生。

我有一个案例,我想将窗口设置MaxHeight为显示我的窗口的屏幕工作区域的高度。我应该参加哪个活动?

编辑:

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

在窗口显示之前升起

而“ContentRendered”事件是

在可视化呈现窗口内容时引发。

这与 MSDN 文档关于该Loaded事件的说法相矛盾:

当元素布局、渲染并准备好交互时发生。

现在这更令人困惑。

4

4 回答 4

65

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

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");
}   

在这种情况下,消息Loaded首先出现在消息之后ContentRendered。这证实了文档中的信息。

通常,在 WPF 中,Loaded如果元素:

已布局、渲染并准备好进行交互。

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

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

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

它只会在Loaded事件中起作用。

关于访问 中的元素Window,它们的工作方式相同。Label让我们在 mainGrid中创建一个Window。在这两种情况下,我们都成功获得了访问权限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());
}   

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

例如,我们要添加一个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;
}

Loaded事件的情况下,在出现时立即Button添加。在事件的情况下,添加到它的所有内容之后都会出现。GridWindowContentRenderedButtonGrid

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

于 2013-08-27T06:02:00.577 回答
49

如果您访问此链接https://docs.microsoft.com/en-us/previous-versions/dotnet/netframework-4.0/ms748948(v=vs.100)#window-lifetime-events并向下滚动到窗口生命周期事件它会向您显示事件顺序。

打开:

  1. 源头启动
  2. 活性
  3. 已加载
  4. 内容渲染

关闭:

  1. 结束
  2. 停用
  3. 关闭
于 2013-08-26T21:26:56.570 回答
12

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

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

<MenuItem Header="{Binding NewGame_Name}" Command="{Binding NewGameCommand}" />
于 2014-04-16T01:26:17.557 回答
-2

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

我用它来避免所有需要很长时间才能出现的应用程序中的闪屏。

    // 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
    }
于 2020-04-29T14:54:48.483 回答