Ответ 1
Я думаю, что между этими двумя событиями мало различий. Чтобы понять это, я создал простой пример манипуляции:
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
.