Problem:
If my DataGrid
is not entirely visible (horizontal & vertical scrollbars are showing) and I click on one of my cells that is partially visible, the grid auto-scrolls to bring that cell into view. I don't want this to happen. I've tried playing around with RequestBringIntoView
, like this:
private void DataGrid_RequestBringIntoView(object sender, RequestBringIntoViewEventArgs e)
{
e.Handled = true;
}
But that does nothing.
Things I've tried:
- My cells are custom
UserControls
; I tried putting an event handler forRequestBringIntoView
on allUserControls
that make up my cells, and tried handling the event, thinking that maybe I wasn't doing enough by just handlingRequestBringIntoView
on theDataGrid
itself. This did not work. - Hosted the
DataGrid
inside of aScrollViewer
, and handled theScrollViewer
'sRequestBringIntoView
event. This actually works, and stops the auto-scrolling behavior, but in my case hosting aDataGrid
inside of aScrollViewer
is not at all desirable, so I need to come up with a different solution.
I'm not sure how to stop this behavior, any ideas?
Define an
EventSetter
in theDataGrid.RowStyle
to call a handler that prevents the row from being brought into view:XAML
Handler
I had the same problem as Rumit, but found a solution/hack.
I thought if I could find a way to differentiate between mouse clicks and arrow keys, then I could set e.Handled accordingly.
After some experimentation I found that e.OriginalSource changed depending on mouse or arrow key. For a mouse click, the handler for RequestBringIntoView is called once and e.OriginalSource was of type DataGridCell. For an arrow key, the handler is called twice and e.OriginalSource is of types DataGridRow and then DataGridCell.
The code for my handler is:
This seems like a bit of a hack, but works great for me.
The l33t way:
Note that this could interfere with e.g. third-party controls.
You can access the DataGrid's internal ScrollViewer by modifying the template. Although normally you wouldn't put an event handler to code behind in a template, if you declare the template inline you can treat the event handler the same way you are when you attach it to the DataGrid itself. This is the default template as generated from Blend including an added handler on the ScrollViewer for the RequestBringIntoView event:
I'm not sure this is working but here is an idea based on some investigation is made in the DataGrid's source code using Reflector:
1/ create a class which inherits DataGridCellsPanel. This is the Panel that is used internally by the DataGrid in order to arrange the cells
2/ override the BringIndexIntoView method by an empty method (without calling the base method)
3/ set the ItemsPanelTemplate property in your XAML:
It seems that when a MouseDown event occurs, at some point the BringIndexIntoView method of the panel is called to do the auto-scroll. Replacing it with a no-op might do the trick.
I hadn't time to test this solution, please let us know if it's working.
I had the same problem and Jan's answer helped me. The only missing thing was that ScrollContentPresenter will be found only after Loaded event occurs. I created an extended DataGrid class inherited from DataGrid with additional property AutoScroll to control if I want the grid to scroll automatically or not.
Here's the class:
And here's how you use it: