2013-08-26 80 views
44

Sự khác nhau giữa các sự kiện Window.LoadedWindow.ContentRendered trong WPF là gì? Sự kiện ContentRendered có được gọi là đầu tiên không?Sự khác biệt giữa các sự kiện Window.Loaded và Window.ContentRendered là gì

Các mô tả về sự kiện Window.ContentRenderedhere chỉ nói

Xảy ra sau khi nội dung của cửa sổ đã được trả lại.

Các mô tả về sự kiện Window.Loadedhere nói

Xảy ra khi nguyên tố này được đặt ra, trả lại, và sẵn sàng cho sự tương tác.

Tôi có trường hợp tôi muốn đặt cửa sổ MaxHeight thành chiều cao của khu vực làm việc của màn hình đang hiển thị cửa sổ của tôi. Tôi nên thực hiện sự kiện nào?

Chỉnh sửa:

Tôi nghĩ rằng tôi đã tìm thấy những gì tôi đang tìm kiếm, nhưng tôi thậm chí còn bối rối hơn bây giờ. Sự kiện Loaded xảy ra trước tiên và sau đó sự kiện ContentRendered xảy ra. Trong Lập trình cuốn sách WPF Chris Sells & Ian Griffiths, nó nói rằng sự kiện Loaded

Lớn lên ngay trước khi cửa sổ được hiển thị

Trong khi 'sự kiện ContentRendered` là

Tăng lên khi nội dung của cửa sổ được hiển thị trực quan.

này mâu thuẫn với những gì các tài liệu MSDN nói về sự kiện Loaded:

Xảy ra khi nguyên tố này được đặt ra, trả lại, và sẵn sàng cho sự tương tác.

Điều này thậm chí còn khó hiểu hơn bây giờ.

Trả lời

44

Tôi nghĩ rằng có rất ít sự khác biệt giữa hai sự kiện. Để hiểu điều này, tôi đã tạo ra một ví dụ đơn giản để thao tác:

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

Trong trường hợp này thông điệp Loaded xuất hiện lần đầu tiên sau khi được thông báo ContentRendered. Điều này xác nhận thông tin trong tài liệu.

Nói chung, trong WPF các Loaded cháy kiện nếu phần tử:

được đặt ra, trả lại, và sẵn sàng cho sự tương tác.

Vì trong WPF, Window là cùng một yếu tố, nhưng thường phải là nội dung được sắp xếp trong bảng điều khiển gốc (ví dụ: Grid). Do đó, để theo dõi nội dung của Window và tạo sự kiện ContentRendered. Ghi chú từ MSDN:

Nếu cửa sổ không có nội dung, sự kiện này không được nâng lên.

Nghĩa là, nếu chúng ta tạo ra một 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" /> 

Nó sẽ chỉ hoạt động Loaded sự kiện.

Về quyền truy cập vào các phần tử trong Window, chúng hoạt động theo cùng một cách. Hãy tạo một số Label trong chính Grid của Window. Trong cả hai trường hợp, chúng tôi đã nhận được thành công quyền truy cập vào 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()); 
} 

Đối với StylesTemplates, ở giai đoạn này chúng được áp dụng thành công, và trong những sự kiện này, chúng tôi sẽ có thể truy cập chúng.

Ví dụ, chúng ta muốn thêm một 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; 
} 

Trong trường hợp của Loaded sự kiện, Button để thêm vào Grid ngay tại sự xuất hiện của Window. Trong trường hợp của ContentRendered sự kiện, Button để thêm vào Grid sau khi tất cả nội dung của nó sẽ xuất hiện.

Do đó, nếu bạn muốn thêm các mục hoặc thay đổi trước khi tải Window bạn phải sử dụng sự kiện Loaded. Nếu bạn muốn thực hiện các hoạt động liên quan đến nội dung của Window chẳng hạn như chụp ảnh màn hình, bạn sẽ cần sử dụng sự kiện ContentRendered.

+0

Sẽ quan tâm để xem sự kiện nào được nâng lên khi cửa sổ vẽ lại, ví dụ: thu nhỏ cửa sổ và sau đó khôi phục cửa sổ. Sự kiện 'Loaded' của cửa sổ có được nâng lên lần nữa không? 'ContentRendered' là người duy nhất được nêu ra? –

+1

@Tony Vitabile: Có, các sự kiện này sẽ hoạt động một lần, lúc bắt đầu 'Cửa sổ' (giảm thiểu và khôi phục không ảnh hưởng). Thông thường, 'Loaded' kích hoạt lần thứ hai một vật thể bị loại bỏ khỏi cây logic, và được giới thiệu lại, sau đó nó sẽ cháy. –

+1

Tôi đã thử nghiệm điều này và đó là kinh nghiệm của tôi rằng sự kiện 'Loaded' kích hoạt trước khi cửa sổ được hiển thị, trong khi sự kiện' ContentRendered' kích hoạt sau khi nó được hiển thị. Điều thú vị là khi 'Loaded' cháy, bố cục & số đo vượt qua dường như hoàn thành như' ActualHeight' và 'ActualWidth' được đặt. Cửa sổ chưa được rút ra. –

8

Nếu bạn đang sử dụng ràng buộc dữ liệu, thì bạn cần sử dụng sự kiện ContentRendered.

Đối với mã bên dưới, Tiêu đề là NULL khi sự kiện được tải lên được nâng lên. Tuy nhiên, Tiêu đề nhận được giá trị của nó khi sự kiện ContentRendered được nâng lên.

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