WPF中的Window.Loaded
和Window.ContentRendered
事件之间有什么区别? ContentRendered
事件被称为第一个?
Window.ContentRendered
事件here的说明只是说
在渲染窗口内容后发生。
Window.Loaded
事件here的说明
在布置,渲染和准备交互元素时发生。
我有一个案例,我想将窗口的MaxHeight
设置为显示我的窗口的屏幕的工作区域的高度。我应该在哪个事件中进行?
编辑:
我想我找到了我想要的东西,但现在我更加困惑了。首先发生Loaded
事件,然后发生ContentRendered
事件。在Chris Sells编写的WPF编程一书中Ian Griffiths,它说Loaded
事件是
在显示窗口之前升起
'ContentRendered`事件是
在视觉上呈现窗口内容时触发。
这与MSDN文档中关于Loaded
事件的说法相矛盾:
在布置,渲染和准备交互元素时发生。
现在更令人困惑。
答案 0 :(得分:52)
我认为两个事件之间几乎没有什么区别。为了理解这一点,我创建了一个简单的操作示例:
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
的主Grid
中创建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());
}
至于Styles
和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
会在Grid
出现时立即添加到Window
。对于ContentRendered
事件,Button
在其所有内容出现后添加到Grid
。
因此,如果您想在加载Window
之前添加项目或更改,则必须使用Loaded
事件。如果您想执行与Window
内容相关的操作,例如截屏,则需要使用事件ContentRendered
。
答案 1 :(得分:42)
如果您访问此链接https://msdn.microsoft.com/library/ms748948%28v=vs.100%29.aspx#Window_Lifetime_Events并向下滚动至Window Lifetime Events,它将显示活动订单。
打开:
关闭:
答案 2 :(得分:10)
如果您正在使用数据绑定,则需要使用ContentRendered事件。
对于下面的代码,引发Loaded事件时Header为NULL。 但是,当引发ContentRendered事件时,Header会获取其值。
<MenuItem Header="{Binding NewGame_Name}" Command="{Binding NewGameCommand}" />
答案 3 :(得分:-2)
这与Window.ContentRendered
和Window.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
}