1

我需要确定画布中包含的子项的绘制顺序。所以我遇到了这个问答:

如何比较属于同一逻辑/视觉树的两个 WPF 控件的相对 Z 顺序?

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

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();

我的理论是,排序发生在新控件甚至定义了父控件之前,因为它稍后会被某些事件设置。问题是我不知道那是什么事件以及我是否可以听它。

有人有想法么?

4

1 回答 1

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();
}

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

于 2012-11-15T00:32:58.310 回答