I am using WPF DataGrid which has ~50 rows. I am using MVVM pattern. User can search for some text in a row and datagrid should highlight the row (not necessarily select the row) and scroll to that row if that row is not visible on screen yet.
Trimmed XAML code:
<DataGrid ItemsSource="{Binding MyDataView,Mode=TwoWay}" Name="myDataGrid"
AutoGeneratingColumn="Generate_Column"
CurrentCell="{Binding DGCurrentCell, Mode=OneWayToSource}" SelectedItem="{Binding SelectedRow, Mode=TwoWay}"
HorizontalScrollBarVisibility="Disabled" VirtualizingPanel.ScrollUnit="Item"
VirtualizingStackPanel.VirtualizationMode="Recycling" VirtualizingStackPanel.IsVirtualizing="False"
IsSynchronizedWithCurrentItem="True">
Code Behind:
public void ScrollToItem(object gridObj, object item)
{
myDataGrid.Dispatcher.BeginInvoke((Action)(() =>
{
myDataGrid.Focus();
myDataGrid.UpdateLayout();
myDataGrid.ScrollIntoView(item);
}));
}
ViewModel:
protected override bool FindItem(string searchString)
{
bool itemFound=false;
DataRow[] rows = this.MyDataTable.Select(searchString);
if (rows.Count() > 0)
{
itemFound = true;
//Scroll to the first row which is a match
(this.View as SCDataGridView).ScrollToItem(this, rows[0]);
}
return itemFound;
}
ScrollToItem API is called if item is found, but scrollviewer never scrolls to that item. I tried various combinations for the following fields but nothing has helped me so far:
HorizontalScrollBarVisibility- Auto or Disabled
VirtualizingPanel.ScrollUnit- Pixel or Item
VirtualizingStackPanel.VirtualizationMode- Standard or Recycling
VirtualizingStackPanel.IsVirtualizing - True or False
What am I missing?
Thanks,
RDV
I found the issue why ScrollIntoView
didnt work for me. ScrollIntoView
requires the exact object type bound to ItemsSource. In my case ItemsSource was bound to MyDataView and every item was of type DataRowView. When calling ScrollIntoView
, i was passing DataRow object and hence it was not working.
Once I passed correct DataRowView object, it worked. I didnt have to set the SelectedItem to this item (as I didnt want to select the item, just scroll to the searched item). Following is the working sample - I didnt have to call UpdateLayout() or beginInvoke
public void ScrollToItem(object gridObj, int itemIdx)
{
myDataGrid.ScrollIntoView((this.DataContext).MyDataView[itemIdx], null);
}
Another important thing i realized while debugging this is that to set Virtualization on or off on a DataGrid/List etc., one should use ScrollViewer.CanScrollContent
instead of VirtualizingPanel.ScrollUnit
property as ScrollViewer.CanScrollContent
is passed to scrollviewer which is actually responsible for implementing virtualization.
Again, true/false value of ScrollViewer.CanScrollContent
has no impact on ScrollIntoView
functioning.
Hope this helps someone.
RDV