我正在使用 WPF DataGrid,它有大约 50 行。我正在使用 MVVM 模式。 用户可以搜索一行中的某些文本,数据网格应突出显示该行(不一定选择该行)并滚动到该行(如果该行在屏幕上不可见)。
修剪后的 XAML 代码:
<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">
背后代码:
public void ScrollToItem(object gridObj, object item)
{
myDataGrid.Dispatcher.BeginInvoke((Action)(() =>
{
myDataGrid.Focus();
myDataGrid.UpdateLayout();
myDataGrid.ScrollIntoView(item);
}));
}
视图模型:
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,但滚动查看器永远不会滚动到该项目。 我尝试了以下字段的各种组合,但到目前为止没有任何帮助:
HorizontalScrollBarVisibility- Auto or Disabled
VirtualizingPanel.ScrollUnit- Pixel or Item
VirtualizingStackPanel.VirtualizationMode- Standard or Recycling
VirtualizingStackPanel.IsVirtualizing - True or False
我错过了什么?
谢谢,
RDV
我发现了为什么
ScrollIntoView
对我不起作用的问题。 ScrollIntoView
需要绑定到 ItemsSource 的确切对象类型。在我的例子中,ItemsSource 绑定到 MyDataView,并且每个项目都是 DataRowView 类型。当调用 ScrollIntoView
时,我正在传递 DataRow 对象,因此它不起作用。
一旦我传递了正确的 DataRowView 对象,它就起作用了。我不必将 SelectedItem 设置为此项目(因为我不想选择该项目,只需滚动到搜索到的项目)。 以下是工作示例 - 我不必调用 UpdateLayout() 或 beginInvoke
public void ScrollToItem(object gridObj, int itemIdx)
{
myDataGrid.ScrollIntoView((this.DataContext).MyDataView[itemIdx], null);
}
我在调试时意识到的另一件重要的事情是,要在 DataGrid/List 等上设置虚拟化打开或关闭,应该使用
ScrollViewer.CanScrollContent
而不是 VirtualizingPanel.ScrollUnit
属性,因为 ScrollViewer.CanScrollContent
被传递给实际上负责的滚动查看器实施虚拟化。
再次强调,
ScrollViewer.CanScrollContent
的真/假值对 ScrollIntoView
功能没有影响。
希望这对某人有帮助。
RDV
我的类似版本如何查找并强制数据网格滚动到位置略有不同......虽小,但仍然不同。
public void ScrollToItem(object gridObj, object item)
{
myDataGrid.Dispatcher.BeginInvoke( DispatcherPriority.Normal, (Action)(() =>
{
myDataGrid.UpdateLayout();
myDataGrid.ScrollIntoView(item, null);
SelectedRow = item;
}));
}
在我的例子中,我有隐藏的列,这似乎导致 DataGrid 无法找到并滚动到正确的行,即使在调用
UpdateLayout()
之后也是如此。我的解决方案是指定一个已知的可见列作为第二个参数。
UpdateLayout();
PresetsDataGrid.ScrollIntoView(preset, PresetsDataGrid.Columns[0]);