2010-07-04 73 views
1

我正在編寫一個WPF控件,它根據窗口/用戶控件後代在其血緣列表中的哪些類型(使用約定進行的實驗的一部分)動態更改其內容與配置)。因此,我需要一些代碼在我的控制完全合格後(即一直到顯示的窗口)運行。理想情況下,我還希望我的代碼在第一次度量/排列傳遞之前運行,因爲我的代碼將更改控件的內容並強制執行另一個度量/排列傳遞。在元素完全父元素之後觸發的WPF事件,但在它被安排之前

我已經看過EndInit,但是在從XAML加載控件之後觸發,此時它可能沒有完全父對象。 (例如,如果我的控件位於UserControl上,那麼一旦UserControl被加載,EndInit就會被觸發 - 但是在其他任何事情發生之前,我想等到UserControl完成一些事情,並且這是其他事情的父代, 。一路上漲)

目前我只是掛鉤從我控制的構造Loaded事件,並運行我的代碼有(奇怪的是,WPF沒有一個裝載的方法覆蓋):

public class MyControl 
{ 
    public MyControl() 
    { 
     Loaded += (sender, e) => { ... }; 
    } 
} 

這是有效的 - 當父母完全填充時,它會觸發 - 但它的略微不是最佳狀態,因爲在加載前會發生測量/排列傳遞。

有沒有一個好的地方我可以把我的代碼放到父母都設置好之後,但在第一次測量/安排通行證之前運行?

爲Silverlight,ElementHost,Blend/VS設計器和VisualBrush工作的解決方案的額外酷炫點(即,不假定頂級父窗口是Window,或者在VisualBrush的情況下,不假設甚至有父母 - 就像它在屏幕上顯示或發送到打印機之前一樣,或者其他任何東西)。

回答

0

我相信父設置後的父母都設置在一個單一的調度運行,所以你應該能夠把你的邏輯在一個委託和排隊它作爲下一個調度操作以獲取該行爲:

protected override void OnVisualParentChanged(DependencyObject oldParent) 
{ 
    base.OnVisualParentChanged(oldParent); 
    this.Dispatcher.BeginInvoke(new Action(OnReady)); 
} 

private void OnReady() 
{ 
    // Element should be fully parented here 
} 

你也可以做到這一點從EndInit而不是,如果你要處理沒有父母的情況下,雖然EndInit似乎被調用一次以上,所以你需要重複檢查OnVisualParentChanged

private bool readyQueued; 

public override void EndInit() 
{ 
    base.EndInit(); 
    if (!readyQueued) 
    { 
     this.Dispatcher.BeginInvoke(new Action(OnReady)); 
     readyQueued = true; 
    } 
} 

private void OnReady() 
{ 
    readyQueued = false; 
    // Element should be fully parented here 
} 
相關問題