2012-11-15 1 views
1

Мне нужно было определить порядок рисования детей, содержащихся на холсте. Так что я натыкался на этот Q/A:Нахождение порядка рисования на WPF Canvas.Children Issue

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

Я считаю, что нашел решение.

Я не знаю ни одного события, которое срабатывало бы с холста, но я знаю, что каждый из моих пользовательских элементов управления имеет событие 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(); 
} 

Поскольку бывают случаи, когда я Добавив несколько дети в одном вызове метод будет выполняться только после загрузки всех элементов управления. Ошибки ушли так, надеюсь, это было проблемой.