在WPF Canvas.Children问题上查找绘制顺序

时间:2012-11-15 00:18:42

标签: c# wpf

我需要确定画布中包含的子画面的绘制顺序。所以我遇到了这个Q / A:

How to compare the relative Z order of two WPF controls that are part of the same logical/visual tree?

这在大多数情况下都能正常工作,但有时我会从此代码中收到错误:

private Panel FindWindowRoot(FrameworkElement child)
{
    FrameworkElement current = child;
    while(current as Window == null)
    {
        current = (FrameworkElement)VisualTreeHelper.GetParent(current); 
    }
    return ((Window)current).Content as Panel;
}

调用VisualTreeHelper.GetParent(current)最终会抛出异常“值不能为空。”

以下是我如何使用DrawOrderComparer

的一个示例
ucVertexControl Control = new ucVertexControl(vertex);
cnvDrawingArea.Children.Add(Control);
SortedChildren = cnvDrawingArea.Children.OfType<FrameworkElement>().OrderByDescending(x => x, new Classes.DrawOrderComparer()).Cast<UIElement>().ToList();

我的理论是,在新控件甚至已定义父级之前进行排序,因为稍后某些事件会对其进行设置。问题是我不知道那是什么事,我是否可以听。

有人有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我相信我找到了解决方案。

我不知道会从画布中触发任何事件,但我知道我的每个用户控件都有一个Loaded事件。所以我改变了这个:

ucVertexControl Control = new ucVertexControl(vertex);
cnvDrawingArea.Children.Add(Control);
SortedChildren = cnvDrawingArea.Children.OfType<FrameworkElement>().OrderByDescending(x => x, new Classes.DrawOrderComparer()).Cast<UIElement>().ToList();

对此:

ucVertexControl Control = new ucVertexControl(vertex);
Control.Loaded += new RoutedEventHandler(Control_Loaded);
cnvDrawingArea.Children.Add(Control);

Control_Loaded函数只是转身并调用此方法:

private void UpdateSortedChildren()
{
    if (cnvDrawingArea.Children.OfType<FrameworkElement>().Any(x => !x.IsLoaded)) return;
    SortedChildren = cnvDrawingArea.Children.OfType<FrameworkElement>().OrderByDescending(x => x, new Classes.DrawOrderComparer()).Cast<UIElement>().ToList();
}

由于有时我在一次调用中添加多个子节点,因此只有在加载了所有控件后才会执行该方法。错误已经消失,所以希望这是问题所在。