Reputation: 329
I asked a few months ago similarly question, but now I have different problem and I am not sure how to solve that.
Picture below describes what I want to implement - in fact I want DataGrid behavior. With 'fixed' keyword I mean that:
1) Header is always visible when I use vertical scrollbar, and header is moving if I use horizontal scrollbar 2) Rows are always visible when I use horizontal scrollbar, and rows are moving if I use vertical scrollbar
I need to create Grid on dynamically way, because I don't know number of rows or columns in advance.
My current solution doesn't include 'fixed rows' and my vertical scroll bar is not visible always (orange line at picture).
XAML
<Grid>
<Grid Grid.IsSharedSizeScope="True">
<ScrollViewer CanContentScroll="True" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Disabled" Grid.Row="2" Grid.ColumnSpan="2">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="600" />
</Grid.RowDefinitions>
<Grid x:Name="HeaderDaysGrid" Margin="10,0,0,0" Grid.Row="0" ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150" MaxWidth="150"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
<ColumnDefinition Width="*" MaxWidth="240"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="35"/>
</Grid.RowDefinitions>
</Grid>
<Grid x:Name="SchedulerGridWrapper" Grid.Row="1" Margin="10,0,0,5">
<ScrollViewer x:Name="SchedulerScrolViewer" HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto" Height="600">
<Grid x:Name="WeekSchedulerGrid" ShowCustomGridLines="False" ScrollViewer.CanContentScroll="True" />
</ScrollViewer>
</Grid>
</Grid>
</ScrollViewer>
</Grid>
</Grid>
And in code behind I have something like this:
private void CreateWeekGrid()
{
WeekSchedulerGrid.Children.Clear();
WeekSchedulerGrid.RowDefinitions.Clear();
WeekSchedulerGrid.ColumnDefinitions.Clear();
HeaderDaysGrid.Children.Clear();
CreateColumnDefinition(WeekSchedulerGrid, NUMBER_OF_COLUMNS, GRID_COLUMN_WIDTH);
CreateRowDefinition(ref WeekSchedulerGrid, _numberOfRows);
for(int row = 0; row < _numberOfRows; row++)
{
TextBlock textBlock = new TextBlock { Text = "Some row name"};
Grid.SetRow(textBlock, row);
Grid.SetColumn(textBlock, 0);
WeekSchedulerGrid.Children.Add(textBlock);
}
foreach (var item in _headerList)
{
HeaderDaysGrid.Children.Add(item);
}
}
private void CreateRowDefinition(ref SchedulerGrid grid, int numberOfRows)
{
for (int row = 0; row < numberOfRows; row++)
{
RowDefinition gridRow = new RowDefinition();
gridRow.MinHeight = 100;
gridRow.MaxHeight = 300;
grid.RowDefinitions.Add(gridRow);
}
}
private void CreateColumnDefinition(ref SchedulerGrid grid, int numberOfColumns, int columnWidth)
{
for (int colIndex = 0; colIndex < numberOfColumns; colIndex++)
{
ColumnDefinition gridCol = new ColumnDefinition();
grid.ColumnDefinitions.Add(gridCol);
if (colIndex == 0)
{
gridCol.Width = new GridLength(1, GridUnitType.Star);
gridCol.MaxWidth = 150;
}
else
{
gridCol.Width = columnWidth;
}
}
}
With this solution I am not sure how to implement 'fixed rows' and to have functionalities described on the picture. Code behind, XAML and binding or something else?
I probably can't join 'fixed rows' and all cells in one grid - because of scroll bar. 'Fixed rows', 'fixed header' and 'all cells' needs to be separate grid? But how to create such a layout and desired behavior? I'm really not sure.
In addition, this custom grid is used like scheduler and shows some custom events(user controls) in his cells, so I probably can't use DataGrid. And sorry for bad English.
Upvotes: 2
Views: 2826
Reputation: 329
I resolved the problem on next way. I have three grids. If you look at the image 'Fixed header', 'Fixed rows' and 'Gray surface for content' are separate grids now. Also I have three scroll viewers. Only the scroll viewer for content is visible. Other scroll viewers are set as hidden, but I update theirs values in code behind when content scroll viewer position is changed.
XAML
<Grid">
<Grid.RowDefinitions>
<RowDefinition Height="40" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="200"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="HeaderDaysScrolViewer" CanContentScroll="True" Grid.Row="0" Grid.Column="1" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="HeaderDaysGrid" Margin="10,0,0,0" ShowGridLines="False"/>
</ScrollViewer>
<ScrollViewer x:Name="VerticalScrolViewer" CanContentScroll="True" Grid.Row="1" Grid.Column="0"
HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="VerticalDataGrid" ShowCustomGridLines="True" GridLineThickness="0.5" GridLineBrush="#FF434343"/>
</ScrollViewer>
<ScrollViewer x:Name="SchedulerScrolViewer" HorizontalScrollBarVisibility="Visible" VerticalAlignment="Stretch"
VerticalScrollBarVisibility="Visible" ScrollChanged="SchedulerScrolViewer_ScrollChanged" Grid.Row="1" Grid.Column="1" Margin="10,0,0,5">
<Grid>
<Grid x:Name="WeekSchedulerGrid" ShowCustomGridLines="False" ScrollViewer.CanContentScroll="True"/>
</Grid>
</ScrollViewer>
</Grid>
Code behind
private void SchedulerScrolViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
{
HeaderDaysScrolViewer.ScrollToHorizontalOffset(e.HorizontalOffset);
OverviewTypesScrolViewer.ScrollToVerticalOffset(e.VerticalOffset);
}
Upvotes: 2
Reputation: 166
<Grid>
<Grid.RowDefinitions>
<RowDefinition x:Name="HeaderDays" Height="35"/>
<RowDefinition x:Name="ScrollAreaRows" Height="600"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition x:Name="HeaderRows" Width="35"/>
<ColumnDefinition x:Name="ScrollAreaColumns" Width="600"/>
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="DataScroller" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Visible" Grid.Row="1" Grid.Column="1">
<Grid x:Name="DataGrid" Height="{Binding Height, ElementName=ScrollAreaRows, UpdateSourceTrigger=PropertyChanged}" Widht="{Binding Width, ElementName=ScrollAreaColumns, UpdateSourceTrigger=PropertyChanged}">
</ScrollViewer>
the grid named "DataGrid" is the one that should scroll horizontally and vertically, while letting row0 and column0 of the outside grid to visually "stay static".
Upvotes: 0