如何获得WPF DataGridCell可视水平(X轴)位置?

Nés*_* A. 3 wpf datagrid

我需要获取WPF DataGridCell的位置,在DataGrid单元格中更改事件获得,但只能获得垂直(Y轴).尽管指向了不同的列,但水平保持不变.

这是几乎可以工作的代码.点击不同的单元格进行测试.

/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    List<Person> Persons = new List<Person>();

    public MainWindow()
    {
        InitializeComponent();

        Persons.Add(new Person { Id = 1, Name = "John", City = "London" });
        Persons.Add(new Person { Id = 2, Name = "Charles", City = "Rome" });
        Persons.Add(new Person { Id = 3, Name = "Paul", City = "Chicago" });

        this.EditingDataGrid.ItemsSource = Persons;
        this.EditingDataGrid.CurrentCellChanged += new EventHandler<EventArgs>(EditingDataGrid_CurrentCellChanged);
    }

    void EditingDataGrid_CurrentCellChanged(object sender, EventArgs e)
    {
        DataGridCell Cell = GetCurrentCell(this.EditingDataGrid);
        var Position = Cell.PointToScreen(new Point(0, 0));
        // WHY X NEVER CHANGES??!!
        MessageBox.Show("X=" + Position.X.ToString() + ", Y=" + Position.Y.ToString(), "Position");
    }

    /// <summary>
    /// Returns, for this supplied Source Data-Grid, the current Data-Grid-Cell.
    /// May return null if no associated Cell is found.
    /// </summary>
    public static DataGridCell GetCurrentCell(DataGrid SourceDataGrid)
    {
        if (SourceDataGrid.CurrentCell == null)
            return null;

        var RowContainer = SourceDataGrid.ItemContainerGenerator.ContainerFromItem(SourceDataGrid.CurrentCell.Item);
        if (RowContainer == null)
            return null;

        var RowPresenter = GetVisualChild<System.Windows.Controls.Primitives.DataGridCellsPresenter>(RowContainer);
        if (RowPresenter == null)
            return null;

        var Container = RowPresenter.ItemContainerGenerator.ContainerFromItem(SourceDataGrid.CurrentCell.Item);
        var Cell = Container as DataGridCell;

        // Try to get the cell if null, because maybe the cell is virtualized
        if (Cell == null)
        {
            SourceDataGrid.ScrollIntoView(RowContainer, SourceDataGrid.CurrentCell.Column);
            Container = RowPresenter.ItemContainerGenerator.ContainerFromItem(SourceDataGrid.CurrentCell.Item);
            Cell = Container as DataGridCell;
        }

        return Cell;
    }

    /// <summary>
    /// Returns the nearest child having the specified TRet type for the supplied Target.
    /// </summary>
    public static TRet GetVisualChild<TRet>(DependencyObject Target) where TRet : DependencyObject
    {
        if (Target == null)
            return null;

        for (int ChildIndex = 0; ChildIndex < VisualTreeHelper.GetChildrenCount(Target); ChildIndex++)
        {
            var Child = VisualTreeHelper.GetChild(Target, ChildIndex);

            if (Child != null && Child is TRet)
                return (TRet)Child;
            else
            {
                TRet childOfChild = GetVisualChild<TRet>(Child);

                if (childOfChild != null)
                    return childOfChild;
            }
        }

        return null;
    }
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string City { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

DataGrid只是由... <DataGrid x:Name="EditingDataGrid"/> 定义

也许存在获得DataGridCell位置的替代方案?

Fre*_*lad 6

您可以DataGridCell像这样从CurrentCell 获取

void EditingDataGrid_CurrentCellChanged(object sender, EventArgs e)
{
    DataGridCell Cell = GetDataGridCell(EditingDataGrid.CurrentCell);
    var Position = Cell.PointToScreen(new Point(0, 0));
    MessageBox.Show("X=" + Position.X.ToString() + ", Y=" + Position.Y.ToString(), "Position");
}
public static DataGridCell GetDataGridCell(DataGridCellInfo cellInfo)
{
    if (cellInfo.IsValid == false)
    {
        return null;
    }
    var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
    if (cellContent == null)
    {
        return null;
    }
    return cellContent.Parent as DataGridCell;
}
Run Code Online (Sandbox Code Playgroud)

您还可以创建一个扩展方法上DataGrid做到这一点

DataGridExtensions.cs

public static class DataGridExtensions
{
    public static DataGridCell GetCurrentDataGridCell(this DataGrid dataGrid)
    {
        DataGridCellInfo cellInfo = dataGrid.CurrentCell;
        if (cellInfo.IsValid == false)
        {
            return null;
        }
        var cellContent = cellInfo.Column.GetCellContent(cellInfo.Item);
        if (cellContent == null)
        {
            return null;
        }
        return cellContent.Parent as DataGridCell;
    }
}
Run Code Online (Sandbox Code Playgroud)

每当你想获得当前时,你可以使用这样的 DataGridCell

DataGridCell Cell = EditingDataGrid.GetCurrentDataGridCell();
Run Code Online (Sandbox Code Playgroud)