2010-07-04 41 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 
} 
相关问题