代码之家  ›  专栏  ›  技术社区  ›  Joe White

WPF事件,在元素完全为父元素之后,但在其排列之前激发

wpf
  •  1
  • Joe White  · 技术社区  · 15 年前

    因此,我需要一些代码来运行后,我的控件是完全父(即,一直到窗口显示)。理想情况下,我还希望代码在第一次度量/排列通过之前运行,因为我的代码将更改控件的内容并强制另一次度量/排列通过。

    目前,我只是从控件的构造函数中挂接加载的事件,并在那里运行代码(奇怪的是,WPF没有要重写的onload方法):

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

    轻微地

    有没有一个好的地方我可以把我的代码放在父母一路设置好之后,但在第一次测量/安排通过之前运行?

    对于同样适用于Silverlight、ElementHost、Blend/VS设计器和VisualBrush的解决方案,需要额外的冷却点(即,不假设顶级父级是窗口,或者在VisualBrush的情况下,不假设甚至存在 一个父母——只是在它出现在屏幕上之前,或者被送到打印机,或者别的什么地方之前,它都是父母。

    1 回复  |  直到 15 年前
        1
  •  0
  •   Quartermeister    15 年前

    我相信父进程都是在单个调度程序操作中设置的,因此您应该能够通过将逻辑放入委托中并将其作为设置父进程后的下一个调度程序操作进行排队来获得该行为:

    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 而不是 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
    }