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

标签 c# wpf wpf-controls

是否可以比较两个 WPF 控件的相对 Z 顺序(哪一个将绘制在顶部),无论它们在逻辑/可视树结构中的关系以及使用什么布局容器?

我需要它能够确定可能与其他控件重叠的控件的可见区域。我的计划是从控件几何图形开始,并与将使用将 GeometryCombineMode 属性设置为“排除”的 CombinedGeometry 在顶部绘制的所有控件的几何图形相交。

更新: 如果大家感兴趣的话,我使用 gdi32 API 来计算可见区域。

<前> [DllImport("gdi32.dll")] 静态 extern IntPtr CreateRectRgn(int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); [DllImport(“gdi32.dll”)] 静态外部int合并Rgn(IntPtr hrgnDest,IntPtr hrgnSrc1,IntPtr hrgnSrc2,int fnCombineMode); [DllImport(“gdi32.dll”)] 静态 extern int GetRegionData(IntPtr hRgn, uint dwCount, IntPtr lpRgnData); [DllImport(“gdi32.dll”)] 静态 extern bool SetRectRgn(IntPtr hRgn, int nLeftRect, int nTopRect, int nRightRect, int nBottomRect); [DllImport(“gdi32.dll”)] 静态 extern bool DeleteObject(IntPtr hObject);

最佳答案

昨晚我也遇到了类似的问题。我的目标是确定一个控件是否会绘制在另一个控件的前面。我搜索了大约 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;
}

关于c# - 如何比较属于同一逻辑/可视树的两个 WPF 控件的相对 Z 顺序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8186844/

相关文章:

WPF 类组合框自定义控件

.net - 是什么导致 Windows 在此 WPF 功能区应用程序中挂起

c# - .net 应用程序图标存储在哪里?

c# - Entity Framework 查询最大

c# - LINQ 中的动态查询

WPF 数据网格样式

c# - 如何绑定(bind)到 MVVM 中的密码框

c# - 我可以并行添加到 ConcurrentQueue 并从 ConcurrentQueue 中产生吗?

c# - WPF 的 DI 工厂

wpf - 双击 WPF ListView - 如何触发命令而不使用事件处理程序