【问题标题】:WPF event that fires after element is fully parented, but before it's arrangedWPF 事件在元素完全为父元素之后触发,但在它被安排之前
【发布时间】:2010-07-04 14:43:17
【问题描述】:

我正在编写一个 WPF 控件,该控件根据其父级列表中的 Window/UserControl 后代的类型动态更改其内容(约定与配置实验的一部分)。

因此,我需要一些代码在我的控件完全作为父级之后运行(即一直到正在显示的窗口)。理想情况下,我还希望我的代码在第一次 Measure/Arrange 传递之前运行,因为我的代码将更改控件的内容并强制另一个 Measure/Arrange 传递。

我查看了 EndInit,但它在从 XAML 加载控件后触发,此时它可能不是完全父级的。 (例如,如果我的控件位于 UserControl 上,则 EndInit 将在加载 UserControl 后触发 - 但在它成为其他任何东西的父级之前。我想等到 UserControl 成为某个东西的父级,而那是其他东西的父级,一直向上。)

目前我只是从控件的构造函数中挂钩 Loaded 事件,并在那里运行我的代码(奇怪的是,WPF 没有要覆盖的 OnLoaded 方法):

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

这很有效——当父母完全填充时它会触发——但它稍微不是最佳的,因为在加载之前发生了一个测量/排列通道。

有没有一个好地方可以放置我的代码,以便它在父母一直设置之后但在第一次测量/排列之前运行?

对于同样适用于 Silverlight、ElementHost、Blend/VS 设计器和 VisualBrush 的解决方案的额外酷点(即,不假设顶级父级是 Window,或者在 VisualBrush 的情况下,不假设甚至是一个父级——只是它在出现在屏幕上、被发送到打印机或其他任何东西之前就已经是父级了。

【问题讨论】:

    标签: wpf


    【解决方案1】:

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

    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 执行此操作,尽管EndInit 似乎被多次调用,因此您需要检查重复项:

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-24
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 2011-01-16
      相关资源
      最近更新 更多