How to find row and cell Index of mouse click inside Silverlight DataGrid?

Download Sample Projects (116.00 kb)

Some back I wrote about How to customize display of columns in DataGrid in silverlight application. But this customization was limited to accessing DataGridRow and changing of style as a whole. Recently I have come across lot of questions about knowing what row and what cell was accessed by user and other related questions. So this post is about addressing some of the following questions.

  • How to find row and cell index of user selection in DataGrid?
  • How to find row and column index of mouse click in Silverlight datagrid?
  • How to find row and column index of datagrid depending on mouse click?

I thought this was going to be a stright forward excercise. I was expecting some kind of direct method or property on some event that I could access to answer the question. It turned out that half of this question could be answered directly by using GetIndex method on DataGridRow object. But I could not get direct answer to index of cell that a user selected in datagrid. A lot of answers that I found revolved around adding a event handler for mouse events in the template for a given DataGridColumn. That meant that I will have to attach these event handlers to all the columns. Then the question was what if I added the columns dynamically or some other custom implementation.

Coming from classic Win32 and MFC background, I thought there has to be some kind of API that I could use where I could capture moust position and do some kind of hit test to find out location of mouse click or mouse move position. After digging around the APIs, I found VisualTreeHelper class that gave me what I was looking for. Following code snippet shows how I was able to get the column and row index inside DataGrid where moust position was.


private void GetGridRowColumnIndex(Point pt, DataGrid grid, out int rowIndex, out int colIndex, out object dataContext)
{
 rowIndex = -1;
 colIndex = -1;
 dataContext = null;
 var elements = VisualTreeHelper.FindElementsInHostCoordinates(pt, grid);
 if (null == elements ||
	elements.Count() == 0)
 { 
  return;
 }

 // Get the rows and columns.
 var rowQuery = from gridRow in elements where gridRow is DataGridRow select gridRow as DataGridRow;
 var cellQuery = from gridCell in elements where gridCell is DataGridCell select gridCell as DataGridCell;
 var cells = cellQuery.ToList<DataGridCell>();
 if (cells.Count == 0)
 {
  return;
 }
			
 foreach (var row in rowQuery)
 {
  dataContext = row.DataContext;
  rowIndex = row.GetIndex();
  foreach (DataGridColumn col in grid.Columns)
  {
   var colContent = col.GetCellContent(row);
   var parent = GetParent(colContent, typeof(DataGridCell));
   if (parent != null)
   {
    var thisCell = (DataGridCell)parent;
    if (object.ReferenceEquals(thisCell, cells[0]))
    {
     colIndex = col.DisplayIndex;
    }
   }
  }
 }
}

private void ProductsGrid_MouseMove(object sender, MouseEventArgs e)
{
 int rowIndex, colIndex;
 object dataContext;
 GetGridRowColumnIndex(e.GetPosition(null), ProductsGrid, out rowIndex, 
   out colIndex, out dataContext);
 SelectedRow.Text = string.Format("[Page={0}], [Row={1}] ", ProductsPager.PageIndex, rowIndex);
 SelectedColumn.Text = string.Format(" [Cell={0}] ", colIndex);
 if (null != dataContext)
 {
  var prod = dataContext as Product;
  ProductInfo.Text = string.Format("[{0}, {1}] ", prod.Name, prod.Color);
 }
}

You can download the attached project to see the whole code in action. The implementation is in Home.xaml/cs

blog comments powered by Disqus
Search
Share

Smart Phones Poll

What smart phone do you currently own?





Show Results

Month List