Как сравнить относительный Z-порядок двух элементов управления WPF, являющихся частью одного и того же логического / визуального дерева? - PullRequest
2 голосов
/ 18 ноября 2011

Можно ли сравнить относительный Z-порядок (который будет отображаться сверху) двух элементов управления WPF независимо от их отношения в логической / визуальной древовидной структуре и используемых контейнерах компоновки?

Мне нужноэто позволяет определить видимые области элемента управления, которые могут перекрываться другими.Я планирую начать с геометрии элемента управления и пересечь геометрию всех элементов управления, которые будут рисоваться сверху, используя CombinedGeometry со свойством GeometryCombineMode, установленным в значение «Исключить».

Обновление: если всем интересноиспользовал gdi32 API для вычисления видимой области.</p> <pre><code> [DllImport("gdi32.dll")] static extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); [DllImport("gdi32.dll")] static extern int CombineRgn(IntPtr hrgnDest, IntPtr hrgnSrc1, IntPtr hrgnSrc2, int fnCombineMode); [DllImport("gdi32.dll")] static extern int GetRegionData(IntPtr hRgn, uint dwCount, IntPtr lpRgnData); [DllImport("gdi32.dll")] static extern bool SetRectRgn(IntPtr hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); [DllImport("gdi32.dll")] static extern bool DeleteObject(IntPtr hObject);

1 Ответ

3 голосов
/ 07 марта 2012

Я столкнулся с подобной проблемой прошлой ночью.Цель для меня состояла в том, чтобы определить, будет ли один элемент управления отображен перед другим.Я искал около 45 минут и не смог найти решение, предоставляемое API, поэтому мне пришлось пройтись по визуальному дереву, чтобы выяснить, какое из них будет нарисовано сверху.Итак, я думаю, основываясь на моих исследованиях, мой ответ - нет, вы не можете сравнить относительный z-порядок, не взглянув на визуальное дерево самостоятельно.

Если вам все еще нужно, вот код, который я использовал, чтобы найти относительный порядок z элементов управления (метод InFrontOf), который также учитывает ручную настройку свойства .ZOrder для элементов управления (работает для моего кода, ноне полностью протестирован, не работает, если свойство ZOrder элемента управления установлено в отрицательное значение).

private bool InFrontOf(FrameworkElement c1, FrameworkElement c2){
    Panel root = FindWindowRoot(c1); // Find the root of the document, assumes that c1 and c2 are part of the same document
    Trace.Assert(root != null, "root of ui element is not a window or a panel that contains children");

    int z1 = Math.Max(Panel.GetZIndex(c1), GetDrawOrder(root, c1));
    int z2 = Math.Max(Panel.GetZIndex(c2), GetDrawOrder(root, c2));

    return z1 > z2;
}



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

private int GetDrawOrder(Panel root, FrameworkElement needle)
{
    int result = 0;
    FrameworkElement current = root;
    Queue<FrameworkElement> toSearch = new Queue<FrameworkElement>();
    toSearch.Enqueue(current);
    while(needle != current)
    {
        if(current is Panel)
        {
            Panel p = (Panel) current;
            foreach (FrameworkElement frameworkElement in p.Children)
            {
                toSearch.Enqueue(frameworkElement);
            }
        }
        if (current is ContentControl)
        {
            ContentControl cc = (ContentControl)current;
            if(cc.Content as FrameworkElement != null)
                toSearch.Enqueue(cc.Content as FrameworkElement);
        }
        current = toSearch.Dequeue();
        result++;
    }
    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...