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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With