简体   繁体   中英

How to autoscroll to the bottom of datagrid in wpf

I have DataGrid , which has got 2 modes, ListView and alleryView . When we select an item in GalleryView and switch to ListView the same item gets selected in list view too. But scroll does not scrolls down to the selected item automatically. How to make it work automatically?

XAML File

    <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 File

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

    } 

Behavior file:

     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 file

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

    }

}

These are the I am working with. But the changes are not getting reflected. Item is getting selected on switching but the scroll bar is not going to bottom. I want it to go to bottom of the page when item number ie., SelectedRecordIndex is greater than 10

To scroll DataGrid to particular row (or column) you can use DataGrid.ScrollIntoView , which has two overloads:

ScrollIntoView(Object) - scrolls to specified item in datagrid view (ie row)

ScrollIntoView(Object, DataGridColumn) - scrolls to specified item and column

In your case you rather need first overload. In order oto scroll to last row you could use such code:

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

If you want to do it in the ViewModel you can use a Behaviour.

You can check it in: Scroll WPF ListBox to the SelectedItem set in code in a view model

There explains how to do it with a ListBox, it's the same with a DataGrid.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM