Reputation: 1275
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
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
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
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