Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing 1 scrollbar between two DataGrids

I am making a wpf application that has 2 datagrids and I want them to scroll together. I know that the DataGridView class has a scroll event that you can use make the necessary changes to the other grid, but DataGrids don't have a Scroll event. I MUST use a DataGrid.

This example is good but is not WPF and it's using DataGridView instead of DataGrid. Using one scroll bar to control two DataGridView

What is the best way to have it so that one data grid's scroll bar also will move the data grid's scroll bar in WPF and DataGrids?

like image 475
Lainezor Avatar asked Mar 28 '13 19:03

Lainezor


1 Answers

You can do this by getting the underlying ScrollViewer of both DataGrid's and setting up the event accordingly. Below is a quick example I made that appears to work as you've described.

xaml:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Grid>
        <DataGrid AutoGenerateColumns="True" Height="200" HorizontalAlignment="Left" Margin="52,69,0,0" Name="dataGrid1" VerticalAlignment="Top" Width="200" ItemsSource="{Binding Collection}" />
        <DataGrid AutoGenerateColumns="True" Height="200" HorizontalAlignment="Left" Margin="270,69,0,0" Name="dataGrid2" VerticalAlignment="Top" Width="200" ItemsSource="{Binding Collection}" />
    </Grid>
</Window>

code behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Collections.ObjectModel;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ObservableCollection<Person> _collection = new ObservableCollection<Person>();
        ScrollViewer scrollView = null;
        ScrollViewer scrollView2 = null;

        public MainWindow()
        {
            for (int i = 0; i < 50; i++)
            {
                var p = new Person() { Name = string.Format("{0}", i), Age = i };
                _collection.Add(p);
            }
            this.DataContext = this;
            InitializeComponent();
        }

        void scrollView_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var newOffset = e.VerticalOffset;

            if ((null != scrollView) && (null != scrollView2))
            {
                scrollView.ScrollToVerticalOffset(newOffset);
                scrollView2.ScrollToVerticalOffset(newOffset);
            }
        }

        public ObservableCollection<Person> Collection
        {
            get
            {
                return _collection;
            }
        }

        private ScrollViewer getScrollbar(DependencyObject dep)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dep); i++)
            {
                var child = VisualTreeHelper.GetChild(dep, i);
                if ((null != child) && child is ScrollViewer)
                {
                    return (ScrollViewer)child;
                }
                else
                {
                    ScrollViewer sub = getScrollbar(child);
                    if (sub != null)
                    {
                        return sub;
                    }
                }
            }
            return null;
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            scrollView = getScrollbar(dataGrid1);
            scrollView2 = getScrollbar(dataGrid2);

            if (null != scrollView)
            {
                scrollView.ScrollChanged += new ScrollChangedEventHandler(scrollView_ScrollChanged);
            }
            if (null != scrollView2)
            {
                scrollView2.ScrollChanged += new ScrollChangedEventHandler(scrollView_ScrollChanged);
            }
        }
    }

    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
    }
}

What is happening is that I'm iterating through the VisualTree of both DataGrids upon Window load using getScrollbar. I then set up the scroll changed event for both DataGrids and then scroll to the vertical offset that was just changed inside the scroll changed event handler.

like image 86
d.moncada Avatar answered Oct 15 '22 09:10

d.moncada