How to get visual horizontal position (X axis) of WPF DataGridCell?

I need to get the WPF DataGridCell position received in the event with the changed DataGrid cell, but only you can get the vertical (Y axis). The horizon remains unchanged even though a different column is indicated.

Here is almost working code. Test by clicking on different cells.

/// <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; }
}

DataGrid is defined only ...    <DataGrid x:Name="EditingDataGrid"/>

Maybe there is an alternative for getting this DataGridCell position?

+3
source share
2 answers

You can get DataGridCellfrom CurrentCell like this

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;
}

You can also create an extension method DataGridfor this

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;
    }
}

, DataGridCell

DataGridCell Cell = EditingDataGrid.GetCurrentDataGridCell();
+6

, , - , , DataGridCell, , "Id".

, "", .

<DataGrid x:Name="EditingDataGrid" SelectionUnit="Cell"/>

, , :

void EditingDataGrid_CurrentCellChanged(object sender, EventArgs e)
{
    // this will iterate through all selected cell of the datagrid
    foreach (DataGridCellInfo cellInfo in this.EditingDataGrid.SelectedCells)
    {
        DataGridCell Cell = GetCurrentCell(this.EditingDataGrid, cellInfo);
        if (Cell != null)
        {
            var Position = Cell.PointToScreen(new Point(0, 0));
            MessageBox.Show("X=" + Position.X.ToString() + 
                            ", Y=" + Position.Y.ToString() + 
                            " Content = " + ((TextBlock)Cell.Content).Text.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 grid, DataGridCellInfo cellInfo)
{
    DataGridCell result = null;
    DataGridRow row = (DataGridRow)grid.ItemContainerGenerator.ContainerFromItem(cellInfo.Item);
    if (row != null)
    {
        int columnIndex = grid.Columns.IndexOf(cellInfo.Column);
        if (columnIndex > -1)
        {
            DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(row);
            result = presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex) as DataGridCell;
        }
    }
    return result;
}

/// <summary>
/// Returns the nearest child having the specified TRet type for the supplied Target.
/// </summary>
static T GetVisualChild<T>(Visual parent) where T : Visual
{
    T child = default(T);
    int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
    for (int i = 0; i < numVisuals; i++)
    {
        Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
        child = v as T;
        if (child == null)
        {
            child = GetVisualChild<T>(v);
        }
        if (child != null)
        {
            break;
        }
    }
    return child;
}

, ,

0

All Articles