WPF DataGrid ScrollIntoView 不会滚动到请求的行

问题描述 投票:0回答:3

我正在使用 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

wpf datagrid scrollview
3个回答
3
投票

我发现了为什么

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


1
投票

我的类似版本如何查找并强制数据网格滚动到位置略有不同......虽小,但仍然不同。

public void ScrollToItem(object gridObj, object item)
{
    myDataGrid.Dispatcher.BeginInvoke( DispatcherPriority.Normal, (Action)(() =>
    {
        myDataGrid.UpdateLayout();
        myDataGrid.ScrollIntoView(item, null);
        SelectedRow = item;
    }));
}

0
投票

在我的例子中,我有隐藏的列,这似乎导致 DataGrid 无法找到并滚动到正确的行,即使在调用

UpdateLayout()
之后也是如此。我的解决方案是指定一个已知的可见列作为第二个参数。

UpdateLayout();
PresetsDataGrid.ScrollIntoView(preset, PresetsDataGrid.Columns[0]);
© www.soinside.com 2019 - 2024. All rights reserved.