Reputation: 165
I caught myself stuck in this problem for a while and I seem to be unable to manage it. I created a UserControl
named TaskListControl
that essentially is a list of another UserControl
named TaskListItemControl
and I want it to show the vertical ScrollBar
when the content overflows but it doesn't happen.
After some searching and test I tried to break down the CustomControl
because I suspect that the problem is related to the undefined space occupation by the items list. I included the ScrollViewer
inside a Grid
and placed it inside the MainWindow
, but nothing changes.
Here is the code for the TaskListItem contained inside the list:
<UserControl x:Class="CSB.Tasks.TaskListItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CSB.Tasks"
xmlns:core="clr-namespace:CSB.Tasks.Core;assembly=CSB.Tasks.Core"
mc:Ignorable="d"
Height="70"
d:DesignHeight="100" d:DesignWidth="400">
<!-- Custom control that represents a Task. -->
<UserControl.Resources>
<!-- The control style. -->
<Style x:Key="ContentStyle" TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border x:Name="ContainerBorder" BorderBrush="{StaticResource LightVoidnessBrush}"
Background="{StaticResource DeepVoidnessBrush}"
BorderThickness="1"
Margin="2">
<!-- The grid that contains the control. -->
<Grid Name="ContainerGrid" Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Border representing the priority state of the Task:
The color is defined by a ValueConverter according to the PriorityLevel of the Task object. -->
<Border Grid.Column="0"
Width="10"
Background="{Binding Priority, Converter={local:PriorityLevelToRGBConverter}}">
</Border>
<!-- Border containing the Task's informations. -->
<Border Grid.Column="1" Padding="5">
<StackPanel>
<!-- The title of the Task. -->
<TextBlock Text="{Binding Title}" FontSize="{StaticResource TaskListItemTitleFontSize}" Foreground="{StaticResource DirtyWhiteBrush}"/>
<!-- The customer the Taks refers to. -->
<TextBlock Text="{Binding Customer}" Style="{StaticResource TaskListItemControlCustomerTextBlockStyle}"/>
<!-- The description of the Task. -->
<TextBlock Text="{Binding Description}"
TextTrimming="WordEllipsis"
Foreground="{StaticResource DirtyWhiteBrush}"/>
</StackPanel>
</Border>
<!-- Border that contains the controls for the Task management. -->
<Border Grid.Column="2"
Padding="5">
<!-- Selection checkbox of the Task. -->
<CheckBox Grid.Column="2" VerticalAlignment="Center"/>
</Border>
</Grid>
</Border>
<!-- Template triggers. -->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" TargetName="ContainerBorder" Value="{StaticResource VoidnessBrush}"/>
<Setter Property="BorderBrush" TargetName="ContainerBorder" Value="{StaticResource PeterriverBrush}"/>
</DataTrigger>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0:0" To="{StaticResource LightVoidness}" Storyboard.TargetName="ContainerGrid" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0:0" To="Transparent" Storyboard.TargetName="ContainerGrid" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<!-- Content of the control: assignment of the DataContext for design-time testing. -->
<ContentControl d:DataContext="{x:Static core:TaskListItemDesignModel.Instance}"
Style="{StaticResource ContentStyle}"/>
And here is the TaskListControl
code:
<UserControl x:Class="CSB.Tasks.TaskListControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CSB.Tasks"
xmlns:core="clr-namespace:CSB.Tasks.Core;assembly=CSB.Tasks.Core"
mc:Ignorable="d"
d:DesignHeight="500" d:DesignWidth="500">
<!-- Custom control that represents a list of TaskListItemControl. -->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<ScrollViewer Grid.Row="0"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto"
DataContext="{x:Static core:TaskListDesignModel.Instance}"
Height="{Binding RelativeSource={RelativeSource AncestorType=Window, Mode=FindAncestor}, Path=Height}">
<!-- The items shown in the list. -->
<ItemsControl ItemsSource="{Binding Items}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:TaskListItemControl/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</Grid>
As you can see, I set the DataContext
in order to test the controls and I can actually see the ScrollBar
inside the design preview:
EDIT: I managed to show the ScrollBar
but it seems to overflow the Window
that contains the TaskListControl
since I bound it's height to the Window
height that, obviously, takes in account the titlebar too.
Here is the code of the MainWindow
where the control is used:
<Window x:Class="CSB.Tasks.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CSB.Tasks"
mc:Ignorable="d"
Title="{StaticResource MainWindow_TitleText}"
Style="{StaticResource WindowDefaultStyle}"
Height="500"
Width="500"
WindowStartupLocation="CenterScreen">
<WindowChrome.WindowChrome>
<WindowChrome ResizeBorderThickness="{Binding ResizeBorderThickness}"
GlassFrameThickness="0"
CornerRadius="{Binding CornerRadius}"/>
</WindowChrome.WindowChrome>
<local:TaskListControl>
<local:TaskListControl/>
</local:TaskListControl>
The TaskListControl
is placed directly in the Window
since I tried to put it in almost every type of "container" (Border
, StackPanel
, Grid
, etc.) but no luck at all, the height still overflows.
Since I'd like to handle the height directly in the UserControl
definition avoiding to do so every time I use it:
TaskListControl
inside the MainWindow
(what type of container)?TaskListControl
inside the UserControl
definition (now it's bound to the Window height, but it's not correct at all)?Here is the result of what I accomplished until now (you can see the bottom scroll button missing):
Does anyone have any suggestions? Thank you all in advance for the help.
Upvotes: 0
Views: 54
Reputation: 606
For debugging such problems, the best way is to set scrollbar visibility to Visible so you can see how your ScrollViewer grows. Probably it grows bigger than the screen size and if you set the scrollbar visibility to Visible, the bottom scroll button will be missing.
Maybe you have put your user control inside a container that has a height of * so it grows bigger than the screen and the scrollbar will never be shown.
Update: I have checked your project, I believe the problem is the Grid in Windows.xaml. In rows 23-27 change the order of the last two RowDefinitions like this:
<Grid.RowDefinitions>
<RowDefinition Height="{Binding TitleHeight}"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
Upvotes: 1