2011-03-13 97 views
3

我需要获得一个WPF DataGridCell的位置,在DataGrid单元格中获得更改事件,但只能获得垂直(Y轴)。 尽管指出了不同的列,但水平仍保持不变。如何获取WPF DataGridCell视觉水平(X轴)位置?

这里是几乎工作的代码。 单击不同的单元格进行测试。

/// <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 x:Name="EditingDataGrid"/>

可能存在有另一种得到那个DataGridCell位置?

回答

6

您可以从CurrentCell得到DataGridCell这样

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

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

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(); 
+0

这就是解决方案!用您的方法获得的DataGridCell实际上可以正确报告X和Y坐标。谢谢! – 2011-03-13 22:01:25

0

我猜发生了什么事情是,你的网格的默认选择的方式是完全行,你用得到DataGridCell越来越持有的“标识”列的值第一个选定单元格的代码。

您可以尝试将网格的选择模式更改为“单元格”,并使用正确的坐标触发消息框。

<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

号。 – 2011-03-13 05:38:17