I'm not using a DataGrid or a ListView and am using ScrollViewer and Grids to create cells that contain wrap panels of items for each cell column.
I'd like something with a similar behavior to the header columns of a datagrid or listview to keep it frozen while scrolling vertically through the items below it, but have it scroll horizontally.
I currently have the following as the root of my main window which works except for when there's a vertical scrollbar that is displayed the alignment of the items is off.
Notes:
So when the "innerScrollViewer" displays it's vertical scrollbar the items aren't aligned with the outer column headers anymore and the items are shifted to the left due to the right vertical scrollbar. How do I get it to dynamically line things up with the outer column headers for the two scenarios of when a vertical scrollbar is displayed or not?
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Disabled">
<Grid x:Name="mainGrid"
Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ScrollViewer}}, Path=ViewportWidth}">
<RowDefinitions>
<RowDefinition Height="Auto" /> <!-- Contains Header columns dynamically added to be "frozen" -->
<RowDefinition Height="*" /> <!-- "row groupings" -->
</RowDefinitions>
<ScrollViewer x:Name="innerScrollViewer"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto"
Grid.Row="1"
Grid.ColumnSpan="{Binding Path=NumColumns}">
<ItemsControl Name="mainWorkItemsItemsControl"
Width="{Binding ActualWidth, ElementName=mainGrid}"
ItemsSource="{Binding MyGroups}"
ItemTemplate="{StaticResource groupedTemplate}" />
</ScrollViewer>
</Grid>
</ScrollViewer>
<DataTemplate x:Key="groupedTemplate">
<ItemsControl ItemsSource="{Binding GroupItems}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<!-- Creates a grid with one row and the same number of columns as "mainGrid" above with a star sizing for each column -->
<SimpleGrid Rows="Auto"
Columns="{p:PyBinding CommaDelimit($[.NumColumns]\, \'*\')}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding Path=GroupedColumnItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<MyControl />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemContainerStyle>
<Style>
<Setter Property="Grid.Column"
Value="{Binding Path=Index}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</DataTemplate>
You have three choices.
Make vertical scroll bar visible by default for both the scroll viewers (for header and inner) so when inner scroll viewer requires vertical scroll, vertical scroll bar just get enabled without taking any more space.
Bind width property of each columns in header with corresponding columns in grids in rows. so when width of a column of row grid changes it will also change width of corresponding column of header. this will also help you to give a facility to user to re size columns by dragging their borders. but it will require more codes.
Make vertical bar of inner scroll viewer visible and set right margin on header which is equal to width of vertical scroll bar.