user3428422
user3428422

Reputation: 4570

WPF DataGrid - get row number which mouse cursor is on

I am looking to get the row number of which the mouse cursor is on in a DataGrid (So basically on a MouseEnter event) so I can get the DataGridRow item of which the ItemSource is binded too,

The XAML I have for the MouseEvent is...

   <DataGridTextColumn.ElementStyle>
      <Style TargetType="{x:Type TextBlock}">
         <EventSetter Event="MouseEnter" Handler="Event"></EventSetter>
         <Setter Property="ToolTip" Value="{Binding Property}" />
      </Style>
   </DataGridTextColumn.ElementStyle>

The event itself...

  private void Event(object sender, MouseEventArgs e)
  {   
     // I have the DataGrid object itself.
     m_DataGrid.?
  }

Maybe it isnt possible the way I am doing it, but I'd be surprised if it can't be done some way.

Thanks

Upvotes: 7

Views: 8923

Answers (4)

Michael Bernhard
Michael Bernhard

Reputation: 31

I need the DataGridRow below the mouse, in one of my applications, to highlight it. Each Cell has a DataTemplate

<DataTemplate x:Key="templateCenter">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="10 0 10 0">
            <Image Source="{StaticResource Back}" Width="15" Height="15"/>
            <Image Source="{StaticResource ListMove}" Width="35" Height="35"/>
            <Image Source="{StaticResource Forward}" Width="15" Height="15"/>
        </StackPanel>
    </DataTemplate>

To get the coordinates of a DataGridCell, I'm looking for an image of the DataTemplate while moving the mouse. If an Image has been found, I'm able to move up the VisualTree to find my cell and it's coordinates (row, column) when I got an Image. It's not a very generic code - just good for my use.

private void DragDrop_PreviewDragOver(object sender, DragEventArgs e)
    {
        if (e.OriginalSource.GetType() != typeof(Image))
        {
            return;
        }

        Point destination = GetCellLocation((DataGrid)sender, (StackPanel)((Image)e.OriginalSource).Parent);
    }

and this

private Point GetCellLocation(DataGrid datagrid, StackPanel stackpanel)
    {
        DataGridCell cell = (DataGridCell)((ContentPresenter)stackpanel.TemplatedParent).Parent;
        int column = cell.Column.DisplayIndex;
        int row = ((DataGrid)datagrid).Items.IndexOf(stackpanel.DataContext);

        return new Point(column, row);
    }

Hope it helps

Upvotes: 0

Martin Cerman
Martin Cerman

Reputation: 332

This worked for me.

<DataGrid x:Name="dataGridView">
    <DataGrid.Resources>
        <Style TargetType="DataGridRow">
            <EventSetter Event="MouseEnter" Handler="Row_MouseEnter"/>
        </Style>
    </DataGrid.Resources>
</DataGrid>

private void Row_MouseEnter(object sender, MouseEventArgs e)
{
    int index = dataGridView.ItemContainerGenerator.IndexFromContainer((DataGridRow)sender);
}

Upvotes: 1

Sheridan
Sheridan

Reputation: 69987

If you access the DataGridRow object that your mouse is over, then you can find its row index using the DataGridRow.GetIndex method:

private void Event(object sender, MouseEventArgs e)
{
    HitTestResult hitTestResult = 
        VisualTreeHelper.HitTest(m_DataGrid, e.GetPosition(m_DataGrid));
    DataGridRow dataGridRow = hitTestResult.VisualHit.GetParentOfType<DataGridRow>();
    int index = dataGridRow.GetIndex();
}

The GetParentOfType method is actually an extension method that I use:

public static T GetParentOfType<T>(this DependencyObject element) where T : DependencyObject
{
    Type type = typeof(T);
    if (element == null) return null;
    DependencyObject parent = VisualTreeHelper.GetParent(element);
    if (parent == null && ((FrameworkElement)element).Parent is DependencyObject) parent = ((FrameworkElement)element).Parent;
    if (parent == null) return null;
    else if (parent.GetType() == type || parent.GetType().IsSubclassOf(type)) return parent as T;
    return GetParentOfType<T>(parent);
}

Upvotes: 16

user3428422
user3428422

Reputation: 4570

OK, I found the answer to be here...

http://www.scottlogic.com/blog/2008/12/02/wpf-datagrid-detecting-clicked-cell-and-row.html

Don't be confused by the article title..

For my solution I basically used

private void MouseOverEvent(object sender, MouseEventArgs e)
{
        DependencyObject dep = (DependencyObject)e.OriginalSource;

         // iteratively traverse the visual tree
         while ((dep != null) &&
                 !(dep is DataGridCell) &&
                 !(dep is DataGridColumnHeader))
         {
            dep = VisualTreeHelper.GetParent(dep);
         }

         if (dep == null)
            return;

         if (dep is DataGridColumnHeader)
         {
            DataGridColumnHeader columnHeader = dep as DataGridColumnHeader;
            // do something
         }

         if (dep is DataGridCell)
         {
            DataGridCell cell = dep as DataGridCell;

            // navigate further up the tree
            while ((dep != null) && !(dep is DataGridRow))
            {
               dep = VisualTreeHelper.GetParent(dep);
            }

            DataGridRow row = dep as DataGridRow;

           //!!!!!!!!!!!!!* (Look below) !!!!!!!!!!!!!!!!!

         }
    • Now you can obtain your own object by using row.Item, and bingo, its on the correct row index

So all about using the mouse original source and going up he VisualTree until you get to the right element.

Upvotes: 1

Related Questions