【问题标题】:Check visible rows in a WPF DataGrid检查 WPF DataGrid 中的可见行
【发布时间】:2010-10-14 01:58:44
【问题描述】:

我有一个 WPF DataGrid,当屏幕上有太多行无法查看时,它会获得一个垂直滚动条。我想知道的是,当用户滚动时,是否有办法知道顶部可见行是什么。

理想情况下,我希望能够连接一个事件以了解用户何时滚动和滚动,检查顶部可见行以更新一些信息。

【问题讨论】:

    标签: c# .net wpf datagrid


    【解决方案1】:

    订阅 DataGrid 的 ScrollViewer 上的 ScrollViewer.ScrollChanged 事件怎么样?它的事件参数非常广泛,描述了 ScrollViewer 移动了多少以及它的新垂直偏移量是多少。另外,根据 MSDN:

    如果 CanContentScroll 为 true,则 ExtentHeight、ScrollableHeight、ViewportHeight 和 VerticalOffset 属性的值是项目数。如果 CanContentScroll 为 false,则这些属性的值是 Device Independent Pixels。

    CanContentScroll 确实是 DataGrid 的 ScrollViewer 的情况。

    您所要做的就是找到 ScrollViewer:

    ScrollViewer scrollview = FindVisualChild<ScrollViewer>(dataGrid);
    

    使用可以在不同地方找到的 FindVisualChild 的实现(例如:Finding control within WPF itemscontrol)。

    【讨论】:

    • 这实际上是一个不错且可靠的方法。
    【解决方案2】:

    使用以下方法对我有用:

    // mHorizontalScrollBar is the HorizontalScrollBar subclass control's instance
    
    // Get the total item count
    nTotalCount = DataGrid1.Items.Count; 
    
    // Get the first visible row index 
    nFirstVisibleRow = mHorizontalScrollBar.Value;
    
    // Get the last visible row index
    nLastVisibleRow = nFirstVisibleRow + nTotalCount - mHorizontalScrollBar.Maximum;
    

    【讨论】:

    • @DannyBeckett,编辑使答案完全无用(或者,非常不清楚),恢复到原始答案。
    • @Sinatr 我不同意,我已经撤销了你的更改。如果您仍然不同意,请发布问题 Meta Stack Exchange,而不是发起回滚战。
    • @DannyBeckett,在它是一个清晰的分步指南之前(我同意有些糟糕的语言),我相信当时已经给予了支持。我现在遇到了同样的问题,在当前状态下尝试这个答案时,我无法让它工作,甚至否决了它。然后我发现了您的编辑并阅读了原始答案,这更清楚了。让我们保持原样。未来的读者无论如何都会看到我的评论(但不是所有人都能看到我猜的修订,不是我的问题;)。
    • 你是怎么得到mHorizontalScrollBar的?
    【解决方案3】:

    检测滚动很简单

    <DataGrid ScrollViewer.ScrollChanged="DataGrid_ScrollChanged" />
    

    现在你必须获得 ScrollViewer 实例:

    void DataGrid_ScrollChanged(object sender, RoutedEventArgs e)
    {
        var scroll = FindVisualChild<ScrollViewer>((DependencyObject)sender);
        ...
    }
    

    (不确定 FindVisualChild 的来源,但有很多实现,例如here

    然后你就可以了

    int firstRow = (int)scroll.VerticalOffset;
    int lastRow = (int)scroll.VerticalOffset + (int)scroll.ViewportHeight + 1;
    

    【讨论】:

    • 最后一行的正确索引是使用 (int)scroll.VerticalOffset + (int)scroll.ViewportHeight - 1;
    【解决方案4】:

    这是一种过于复杂的方法,但它可能会奏效。首先,继承 DataGridRowsPresenter 并覆盖 OnViewportOffsetChanged method。然后,复制数据网格的标准控件模板,并将 DataGridRowsPresenter 替换为您自己的。我将与视口相关的行的命中测试的详细信息留给您;-)。

    具体来说,您想要完成什么?也许我们可以想出一个更好的方法,因为这可能非常脆弱并且需要大量额外的工作(即在更新控制模板时保持同步)。

    【讨论】:

    • 谢谢。我只是通过使用动画放大网格中的内容(主要是字体)来解决它。不是那么简单,但基本上是我想要的。
    • 我遇到了缩放字体的问题,当缩小字体时,列不会自动调整大小,因此它们仍然是较大字体的宽度。
    • 在 WPFToolkit 的当前版本中有一个错误,当它们与星形大小的列混合时,自动调整大小的列会奇怪地工作。我们也看到了这种行为,而且我们从来没有费心去修复它。
    • 谢谢,实际上,如果我上面的 cmets 没有任何意义,那是因为我一直在处理两个不同的问题,一个是试图找出第一行,另一个是缩放数据网格。我放弃了第一行的事情,并告诉用户他们需要调整 UI。
    【解决方案5】:

    也许是一个迟到的答案,也许不是最好的方法,而是最简单的方法之一。

        public void SelectPatient(string patientID)
        {
            var item = PatientList.FirstOrDefault(ro => ro.Pati_ID == patientID);
            if (item != null)
            {
                grdPatients.SelectedItem = item;
                grdPatients.ScrollIntoView(grdPatients.Items[grdPatients.Items.Count - 1]); //Scrolls to the last row
                grdPatients.UpdateLayout();
                grdPatients.ScrollIntoView(grdPatients.SelectedItem);
                grdPatients.UpdateLayout();
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-27
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      • 2011-04-28
      • 1970-01-01
      • 2010-12-07
      • 1970-01-01
      相关资源
      最近更新 更多