Vishnu Babu
Vishnu Babu

Reputation: 1275

Single scrollbar for multiple DataGrids on a grid WPF

I have two DataGrids on the grid in which one DataGrid is placed exactly below the other, both these DataGrids shares the same column headers what i want to do is that i want to use a single scroll bar (Horizontal Scroll bar) for both these DataGrids . How can i do this ??

 <Grid>
    <DataGrid Name="StatusGrid"
              Height="Auto"
              Width="Auto"
              AutoGenerateColumns="False"
              CanUserAddRows="False"
              CanUserReorderColumns="False" />

    <DataGrid AutoGenerateColumns="False"
              Height="auto"
              Width="auto"
              Margin="0,73,0,10"
              Name="heatMap"
              IsReadOnly="True"
              CanUserReorderColumns="False"
              CanUserSortColumns="False"
              ScrollViewer.CanContentScroll="True"
              ScrollViewer.VerticalScrollBarVisibility="Auto"
              ScrollViewer.HorizontalScrollBarVisibility="Auto"
              ItemsSource="{Binding HeatMapCollection}"
              Background="AliceBlue" />
</Grid>

Upvotes: 2

Views: 2621

Answers (3)

Tomtom
Tomtom

Reputation: 9394

I'm using the following attached-property to synchronize them. (not sure where I get it from)

public class ScrollSynchronizer : DependencyObject
{
    public static readonly DependencyProperty ScrollGroupProperty =
        DependencyProperty.RegisterAttached(
            "ScrollGroup",
            typeof (string),
            typeof (ScrollSynchronizer),
            new PropertyMetadata(OnScrollGroupChanged));

    private static readonly Dictionary<ScrollViewer, string> scrollViewers = new Dictionary<ScrollViewer, string>();
    private static readonly Dictionary<string, double> horizontalScrollOffsets = new Dictionary<string, double>();
    private static readonly Dictionary<string, double> verticalScrollOffsets = new Dictionary<string, double>();

    private static void OnScrollGroupChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ScrollViewer scrollViewer = d as ScrollViewer;
        if (scrollViewer != null)
        {
            if (!string.IsNullOrEmpty((string) e.OldValue))
            {
                if (scrollViewers.ContainsKey(scrollViewer))
                {
                    scrollViewer.ScrollChanged -= ScrollViewerScrollChanged;
                }
            }

            if (!string.IsNullOrEmpty((string) e.NewValue))
            {
                if (horizontalScrollOffsets.ContainsKey((string) e.NewValue))
                {
                    scrollViewer.ScrollToHorizontalOffset(horizontalScrollOffsets[(string) e.NewValue]);
                }
                else
                {
                    horizontalScrollOffsets.Add((string) e.NewValue, scrollViewer.HorizontalOffset);
                }

                if (verticalScrollOffsets.ContainsKey((string) e.NewValue))
                {
                    scrollViewer.ScrollToVerticalOffset(verticalScrollOffsets[(string) e.NewValue]);
                }
                else
                {
                    verticalScrollOffsets.Add((string) e.NewValue, scrollViewer.VerticalOffset);
                }

                scrollViewers.Add(scrollViewer, (string) e.NewValue);
                scrollViewer.ScrollChanged += ScrollViewerScrollChanged;
            }
        }
    }

    private static void ScrollViewerScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        if (e.VerticalChange != 0 || e.HorizontalChange != 0)
        {
            ScrollViewer changedScrollViewer = sender as ScrollViewer;
            Scroll(changedScrollViewer);
        }
    }

    private static void Scroll(ScrollViewer changedScrollViewer)
    {
        string group = scrollViewers[changedScrollViewer];
        verticalScrollOffsets[group] = changedScrollViewer.VerticalOffset;
        horizontalScrollOffsets[group] = changedScrollViewer.HorizontalOffset;

        foreach (
            KeyValuePair<ScrollViewer, string> scrollViewer in
                scrollViewers.Where(s => s.Value == group && s.Key != changedScrollViewer))
        {
            if (scrollViewer.Key.VerticalOffset != changedScrollViewer.VerticalOffset)
            {
                scrollViewer.Key.ScrollToVerticalOffset(changedScrollViewer.VerticalOffset);
            }

            if (scrollViewer.Key.HorizontalOffset != changedScrollViewer.HorizontalOffset)
            {
                scrollViewer.Key.ScrollToHorizontalOffset(changedScrollViewer.HorizontalOffset);
            }
        }
    }

    public static void SetScrollGroup(DependencyObject element, string value)
    {
        element.SetValue(ScrollGroupProperty, value);
    }

    public static string GetScrollGroup(DependencyObject element)
    {
        return (string) element.GetValue(ScrollGroupProperty);
    }
}

And the usage in your DataGrid-Definitions you have to write something like:

nameSpaceOfAttachedProperty:ScrollSynchronizer.ScrollGroup="MyScrollGroup"

With this code you can synchronize the scrolling everywhere.

Upvotes: 1

dontbyteme
dontbyteme

Reputation: 1261

Try using the ScrollViewer like

<ScrollViewer CanContentScroll="True"
              HorizontalScrollBarVisibility="Visible"
              VerticalScrollBarVisibility="Visible">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <DataGrid Grid.Row="0"
                  Name="StatusGrid"
                  Height="Auto"
                  Width="Auto"
                  AutoGenerateColumns="False"
                  CanUserAddRows="False"
                  CanUserReorderColumns="False" />

        <DataGrid Grid.Row="1"
                  AutoGenerateColumns="False"
                  Width="1000"
                  Margin="0,73,0,10"
                  Name="heatMap"
                  IsReadOnly="True"
                  CanUserReorderColumns="False"
                  CanUserSortColumns="False"
                  ItemsSource="{Binding HeatMapCollection}"
                  Background="AliceBlue" />
    </Grid>
</ScrollViewer>

Upvotes: 3

bars222
bars222

Reputation: 1660

You can use ScrollViewer like this.

<ScrollViewer HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <DataGrid Grid.Row="0">
            <DataGrid.Columns>
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
            </DataGrid.Columns>
        </DataGrid>
        <DataGrid Grid.Row="1">
            <DataGrid.Columns>
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
                <DataGridTextColumn Width="200" Header="test" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</ScrollViewer> 

Upvotes: 1

Related Questions