I have a ScrollViewer
bound with a ControlTemplate
(which works fine), a Grid
inside (which overrides the default ScrollViewer
and sets the ScrollBar
s "above" the content and finally I have some EventTrigger
s which set the Opacity of the ScrollBar
s to 1 or 0 in a Storyboard
. They also work well.
What I am missing is one of this triggers that sets the Opacity
to 1 in case the scrolling takes place. It can be scrolled by mouse, mousewheel, stylus or touch, so it would be best to take the ScrollChanged
of the ScrollViewer
or the Scroll
of the ScrollBar
s themselves. But I cannot make it work. Oh and btw. I cannot change the way it is build. So I have to make it by pure XAML inside the ControlTemplate
(I know myself how to make it with code behind, but that is not possible here).
The style looks this way:
<Style TargetType="{x:Type controls:ViewerControl}">
// ... some properties of no interest here
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:ViewerControl}">
<Border Grid.Row="0" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" Name="PART_ScrollViewer">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.Triggers>
<EventTrigger RoutedEvent="Grid.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="00:00:02" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="00:00:02" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Grid.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Grid.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="00:00:02" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="00:00:02" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<ScrollContentPresenter Grid.ColumnSpan="2"
Grid.RowSpan="2"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"/>
<ScrollBar Name="PART_VerticalScrollBar"
HorizontalAlignment="Right"
Opacity="0"
Grid.Column="1"
IsTabStop="False"
Value="{TemplateBinding VerticalOffset}"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<ScrollBar Name="PART_HorizontalScrollBar"
VerticalAlignment="Bottom"
Orientation="Horizontal"
Opacity="0"
Grid.Row="1"
IsTabStop="False"
Value="{TemplateBinding HorizontalOffset}"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<StackPanel IsItemsHost="True" Name="PART_ItemsHost" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tried it with something like this:
<ScrollViewer.Triggers>
<EventTrigger RoutedEvent="ScrollViewer.ScrollChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ScrollViewer.Triggers>
But if I put this directly inside the ScrollViewer
it cannot find the ScrollBar
s and if I put it inside the Grid
it is completly ignored (the Grid
itself has no control over the ScrollViewer
and seems not to bubble this up to it.
I found an answer where someone used the VisualStateManager, but this only seems to work in Silverlight, not in C#. It looked like this:
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="ScrollStates">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="00:00:00.5"/>
</VisualStateGroup.Transitions>
<VisualState x:Name="Scrolling">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</VisualState>
<VisualState x:Name="NotScrolling"/>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
Has someone an idea how to make this work?
CodePudding user response:
A coworker of mine found the answer:
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="ScrollViewer.ScrollChanged">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation Duration="0" From="0" To="1" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
<DoubleAnimation BeginTime="00:00:02" Duration="00:00:01.5" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_VerticalScrollBar"/>
<DoubleAnimation BeginTime="00:00:02" Duration="00:00:01.5" From="1" To="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="PART_HorizontalScrollBar"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
So if you put the EventTrigger
inside the ControlTemplate.Triggers
, it works like a charm... really cool. You only have to put these MouseEnter
and MouseLeave
inside the ScrollBar
s or else they are also triggered if the cursor enters the content of the ScrollViewer
, not only on entering the ScrollBar
s.