如何在WPF数据网格上自动滚动

Chr*_*ert 35 c# wpf datagrid

我觉得我很蠢.我现在搜索了15分钟,发现了几种不同的数据网格滚动解决方案,但似乎没有一个对我有用.

我正在使用WPF与.NET 3.5和WPF Toolkit DataGrid.当我的可观察集合发生变化时,我的网格会更新,完美运行.现在,我的DataGrid位于普通网格内,如果DataGrid太大,则会出现滚动条.还好......

现在来了1.000.000美元的问题:

如何让datagrid滚动到最后一行?有:

  • 没有AutoScroll属性
  • 没有CurrentRowSelected索引
  • 一个CurrentCell,但没有我可以用于CurrentCell = AllCells.Last的Collection

有任何想法吗?我觉得自己真的很蠢,这个问题太难了似乎很奇怪.我错过了什么?

Ara*_*and 49

您应该使用datagrid方法

datagrid.ScrollIntoView(itemInRow);
Run Code Online (Sandbox Code Playgroud)

要么

datagrid.ScrollIntoView(itemInRow, column);
Run Code Online (Sandbox Code Playgroud)

这种方式不会乱七八糟地找到滚动查看器等.

  • @ user1034912如果您对此答案有疑问,您应该提供详细信息,说明为什么它不起作用或者您的情况可能不同,您需要提出另一个问题.自6年前这个问题得到回答以来,底层框架可能发生了一些变化.当网格被虚拟化时,我有时会滚动到视图中.从upvotes的数量来看,很明显这适用于很多人,所以可能问题在于你的代码不是这个答案. (3认同)

Jos*_*nel 43

;)

if (mainDataGrid.Items.Count > 0)
{
    var border = VisualTreeHelper.GetChild(mainDataGrid, 0) as Decorator;
    if (border != null)
    {
        var scroll = border.Child as ScrollViewer;
        if (scroll != null) scroll.ScrollToEnd();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 用`((INotifyCollectionChanged)MyDataGrid.Items)连接起来.CollectionChanged + = Your_Event_Handler;` (3认同)

Den*_*rov 18

我为网格自动滚动编写了一个附加属性:

using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;

public static class DataGridBehavior
{
    public static readonly DependencyProperty AutoscrollProperty = DependencyProperty.RegisterAttached(
        "Autoscroll", typeof(bool), typeof(DataGridBehavior), new PropertyMetadata(default(bool), AutoscrollChangedCallback));

    private static readonly Dictionary<DataGrid, NotifyCollectionChangedEventHandler> handlersDict = new Dictionary<DataGrid, NotifyCollectionChangedEventHandler>();

    private static void AutoscrollChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
    {
        var dataGrid = dependencyObject as DataGrid;
        if (dataGrid == null)
        {
            throw new InvalidOperationException("Dependency object is not DataGrid.");
        }

        if ((bool)args.NewValue)
        {
            Subscribe(dataGrid);
            dataGrid.Unloaded += DataGridOnUnloaded;
            dataGrid.Loaded += DataGridOnLoaded;
        }
        else
        {
            Unsubscribe(dataGrid);
            dataGrid.Unloaded -= DataGridOnUnloaded;
            dataGrid.Loaded -= DataGridOnLoaded;
        }
    }

    private static void Subscribe(DataGrid dataGrid)
    {
        var handler = new NotifyCollectionChangedEventHandler((sender, eventArgs) => ScrollToEnd(dataGrid));
        handlersDict.Add(dataGrid, handler);
        ((INotifyCollectionChanged)dataGrid.Items).CollectionChanged += handler;
        ScrollToEnd(dataGrid);
    }

    private static void Unsubscribe(DataGrid dataGrid)
    {
        NotifyCollectionChangedEventHandler handler;
        handlersDict.TryGetValue(dataGrid, out handler);
        if (handler == null)
        {
            return;
        }
        ((INotifyCollectionChanged)dataGrid.Items).CollectionChanged -= handler;
        handlersDict.Remove(dataGrid);
    }

    private static void DataGridOnLoaded(object sender, RoutedEventArgs routedEventArgs)
    {
        var dataGrid = (DataGrid)sender;
        if (GetAutoscroll(dataGrid))
        {
            Subscribe(dataGrid);
        }
    }

    private static void DataGridOnUnloaded(object sender, RoutedEventArgs routedEventArgs)
    {
        var dataGrid = (DataGrid)sender;
        if (GetAutoscroll(dataGrid))
        {
            Unsubscribe(dataGrid);
        }
    }

    private static void ScrollToEnd(DataGrid datagrid)
    {
        if (datagrid.Items.Count == 0)
        {
            return;
        }
        datagrid.ScrollIntoView(datagrid.Items[datagrid.Items.Count - 1]);
    }

    public static void SetAutoscroll(DependencyObject element, bool value)
    {
        element.SetValue(AutoscrollProperty, value);
    }

    public static bool GetAutoscroll(DependencyObject element)
    {
        return (bool)element.GetValue(AutoscrollProperty);
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

    <DataGrid c:DataGridBehavior.Autoscroll="{Binding AutoScroll}"/>
Run Code Online (Sandbox Code Playgroud)

  • @ user161953我认为访问者需要对此代码进行更多解释..! (2认同)
  • 解释它是如何工作的或如何使用它? (2认同)

小智 8

为了添加AutoScroll To Last元素:

YourDataGrid.ScrollIntoView(YourDataGrid.Items.GetItemAt(YourDataGrid.Items.Count-1));
Run Code Online (Sandbox Code Playgroud)

愿这个帮助:)


Jam*_*Esh 7

我知道这是一个迟到的答案,但只是为了搜索的人,我找到了最简单的方法来滚动到DataGrid的底部.在DataContextChanged事件中把它放在:

myDataGrid.ScrollIntoView(CollectionView.NewItemPlaceholder);
Run Code Online (Sandbox Code Playgroud)

好吧?

这就是它工作的原因:在每个数据网格上,DataGrid底部都有一个位置,您可以在其中添加一个新项目到它所绑定的列表中.这是一个CollectionView.NewItemPlaceholder,只有你的DataGrid中有一个.所以你可以滚动到那个.

  • -1:只有在您向视图添加新视图模型时,datacontext才会更改,因此这将仅在第一次滚动到底部,而不是每次将项目添加到itemsource时 (3认同)
  • 此外,这不是问题. (2认同)

小智 6

listbox.Add(foo);
listbox.SelectedIndex = count - 1;
listbox.ScrollIntoView(listbox.SelectedItem);
listbox.SelectedIndex = -1;
Run Code Online (Sandbox Code Playgroud)