如何获取 WPF DataGrid 单元格的位置?

How do get the location of a WPF DataGrid cell?

我有一个 DataGrid 绑定到 Appointment 个对象的集合。网格显示给定一周的约会,列为天数,行为时间,因此每个单元格都绑定到一个约会。

当用户单击一个单元格时,我想显示一个小的 window,其中包含该单元格约会的摘要。由于复杂的原因,我无法为单元格设置模板来显示摘要,更重要的是,我希望摘要下拉并覆盖所选单元格下方的单元格。

在我链接到单击的命令中,通过一些魔法,我得到了所选单元格本身的 DataGridCellInfo,但该对象没有提供任何定位的提示,只有一些尺寸。双击的输入绑定如下所示:

<DataGrid.InputBindings>
    <!--TODO Remove name 'TheGrid' and find parent DataGrid-->
    <MouseBinding MouseAction="LeftDoubleClick"  Command="{Binding ApptClickCommand}" CommandParameter="{Binding ElementName=TheGrid, Path=SelectedCells}" />
</DataGrid.InputBindings>

命令代码接收一个SelectedCellsCollection类型的参数,其中只包含一个DataGridCellInfo。我没有其他信息可以在命令中使用。事实上,我对 viewmodel 中的视图如此亲密,所以我在作弊,所以我想避免过分直接使用代码隐藏事件。

弹出窗口是 UI 特定的东西,在我看来应该以某种方式从视图中定位。

过去 something similar,我的 ViewModel 跟踪实际数据、SelectedItem 和 IsDetailsVisible 的标志。

从视图中,我会有一个 "popup" UserControl 位于我的网格顶部。它的可见性绑定到 IsDetailsVisible 属性,数据绑定到 SelectedItem。对于我的项目,弹出窗口居中,但是让 View 设置 PopupUserControl 的 Top/Left 属性以便它与用户单击的单元格匹配应该是一个简单的案例。

要在 UI 中找到实际的网格单元格,有几种方法可以解决这个问题。最简单的方法可能是使用 Click 或 MouseDown 事件,然后根据 Clicked DataGridCell 从那里定位 PopupUserControl。正如我所说,这种事情对我来说是视图特定的,所以应该放在视图后面的代码中。

此外,我从不喜欢 WPF 的弹出窗口,因此制作了我自己的自定义 UserControl,我会一直使用它。如果您有兴趣使用它或做类似的事情,可以在我的博客 here 上找到该代码。

下面是一个示例,说明如何获取 DataGridCell 元素,然后使用 Visual.PointToScreen 方法查找其屏幕坐标:

    private void AppClickCommandExecuted(IList<DataGridCellInfo> cells)
    {
        if(cells != null && cells.Count > 0)
        {
            DataGridCellInfo cellInfo = cells[0];
            FrameworkElement cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
            if (cellContent != null)
            {
                DataGridCell cell = cellContent.Parent as DataGridCell;
                if(cell != null)
                {
                    Point screenCoordinates = cell.PointToScreen(new Point(0, 0));
                    //place your popup based on the screen coordinates of the cell...
                }
            }
        }
    }