2013-08-26 159 views
44

WPF中的Window.LoadedWindow.ContentRendered事件有什麼區別? ContentRendered事件是否首先被調用?Window.Loaded和Window.ContentRendered事件有什麼區別

Window.ContentRendered事件here的描述只是說

窗口的內容已經被渲染後發生。

Window.Loaded事件here的描述說

當元件被佈局,已呈現,且可用於交互時發生。

我有一種情況,我想將窗口的MaxHeight設置爲正在顯示我的窗口的屏幕工作區域的高度。我應該參加哪個活動?

編輯:

我想我找到了我一直在尋找,但現在我更糊塗了。 Loaded事件首先發生,然後發生ContentRendered事件。在這本書編程WPF由克里斯·塞爾斯&伊恩·格里菲思,它說,Loaded事件是

窗口前剛剛上調顯示

雖然「ContentRendered`事件是

當視覺呈現窗口的內容時引發。

這違背了什麼的MSDN文檔說,有關的Loaded事件:

當元素已佈局,已呈現且可用於交互時發生。

這現在更令人困惑。

回答

44

我認爲有兩個事件之間的差別不大。爲了理解這一點,我創建了一個簡單的例子來操作:

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中的元素,它們的工作方式相同。我們在Window的主要Grid中創建一個Label。在這兩種情況下,我們已經成功地獲得訪問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()); 
} 

至於StylesTemplates,在這個階段,他們被成功應用,並在這些事件中,我們將能夠訪問它們。

例如,我們要添加一個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

+0

當窗口重新繪製時,會看到會引發什麼事件,例如最小化窗口然後恢復它。窗口的'Loaded'事件再次升高了嗎? ContentRendered是唯一提出的嗎? –

+1

@Tony Vitabile:是的,這些事件將在「窗口」開始時起作用(最小化和恢復不會影響)。通常情況下,'Loaded'會再次觸發一個物品被從邏輯樹中物理刪除,然後再次引入,然後它會觸發。 –

+1

我一直在測試這個,這是我的經驗,'Loaded'事件在呈現窗口之前觸發,而'ContentRendered'事件在呈現之後觸發。有趣的是,當'Loaded'觸發時,由於設置了ActualHeight和ActualWidth,佈局和度量傳遞似乎已完成。該窗口尚未繪製。 –

8

如果您使用的是數據綁定,那麼您需要使用ContentRendered事件。

對於下面的代碼,當引發Loaded事件時,Header爲NULL。 但是,在引發ContentRendered事件時,Header會獲取其值。

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