【问题标题】:How to autoscroll to the bottom of datagrid in wpf如何在wpf中自动滚动到数据网格的底部
【发布时间】:2019-10-30 05:58:25
【问题描述】:

我有DataGrid,它有两种模式,ListView 和alleryView。当我们在GalleryView 中选择一个项目并切换到ListView 时,相同的项目也会在列表视图中被选中。但滚动不会自动向下滚动到所选项目。如何让它自动工作?

XAML 文件

    <DataGrid ItemsSource="{Binding ListItems}" RowStyle="{StaticResource DataGridRowStyle}"
              AutoGenerateColumns="False" RowHeight="60" CanUserAddRows="False" 
              CanUserDeleteRows="False" CanUserResizeRows="False" AlternationCount="2"
              HorizontalGridLinesBrush="LightSteelBlue" VerticalGridLinesBrush="LightSteelBlue"
              SelectionMode="Single" SelectedItem="{Binding SelectedSearchItem}" 
              IsReadOnly="True" KeyboardNavigation.TabNavigation="Once" behaviors:DataGridBehavior.Autoscroll="{Binding Autoscroll}" >

CS 文件

     private void SetSelectedItemOnViewChange()
    {
        if (SelectedViewMode.ModeName == ViewModes[1].ModeName)
            GallerySearchResults.SelectedSearchItem = GallerySearchResults.GalleryItems.FirstOrDefault((x => x.IndexNo == SelectedRecordIndex));


        else if (SelectedViewMode.ModeName == ViewModes[0].ModeName)
        {

            ListSearchResults.SelectedSearchItem = ListSearchResults.ListItems.FirstOrDefault((x => x.IndexNum == SelectedRecordIndex));
            if (SelectedRecordIndex > 10)
                Autoscroll = true;
        }

    } 

行为文件:

     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);
    }
}

xaml.cs 文件

    public partial class ItemGridControl : UserControl
{
    public ItemGridControl()
    {
        InitializeComponent();

    }

}

这些是我正在使用的。但这些变化并没有得到体现。项目在切换时被选中,但滚动条不会到底部。我希望它在项目编号即 SelectedRecordIndex 大于 10 时转到页面底部

【问题讨论】:

  • 您可以使用dataGrid.ScrollIntoView(dataGrid.SelectedItem)滚动到SelectedItem
  • 这必须在哪个文件中提及?
  • 在你的 CS 文件的 SetSelectedItemOnViewChange 方法中
  • 不可能,因为它是一个 ViewModel 并且不能在那里创建数据网格对象
  • 我没有在后面写任何代码

标签: c# .net wpf datagrid


【解决方案1】:

要将DataGrid 滚动到特定的行(或列),您可以使用DataGrid.ScrollIntoView,它有两个重载:

ScrollIntoView(Object) - 滚动到数据网格视图中的指定项目(即行)

ScrollIntoView(Object, DataGridColumn) - 滚动到指定的项目和列

在您的情况下,您宁愿首先重载。为了滚动到最后一行,您可以使用这样的代码:

myDataGrid.ScrollIntoView(myDataGrid.Items[myDataGrid.Items.Count - 1]);

【讨论】:

  • 这必须在后面写代码.. 有什么方法可以使用 ViewModel 吗?因为我不想在 xaml.cs 文件中写任何代码。它只是用于初始化
  • @user3422209 这是代码隐藏。如何将该代码放入 XAML 中??
  • 不在 XAML 中...在 CS 文件中... ViewModel.CS.. 不在 Xaml.cs 中
  • @user3422209 对不起,我不理解你。这是 C# 代码,而不是 XAML。我不明白你哪里有问题。
  • 我有这些文件,XAML、XAML.CS 和 ViewModel.CS.. 如问题中所述。在 xaml.cs 中只调用了构造函数......在 Viewmodel.cs 中我们进行编码
【解决方案2】:

如果您想在 ViewModel 中执行此操作,您可以使用 Behaviour。

您可以签到:Scroll WPF ListBox to the SelectedItem set in code in a view model

这里解释了如何使用 ListBox 进行操作,与 DataGrid 相同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-25
    • 1970-01-01
    • 2021-08-24
    • 2014-02-26
    • 2016-11-13
    • 2011-09-16
    相关资源
    最近更新 更多