Skip to content

Commit d8e8676

Browse files
AmRo045Keboo
andauthored
ScrollViewer Improvement (#1672)
* Add 'IsAutoHideEnabled' and 'CornerRectangleVisibility' properties to ScrollViewerAssist * Set 'PART_Corner' Visibility using TemplateBinding instead of triggers * Optimize PART_VerticalScrollBar and PART_HorizontalScrollBar triggers * Remove scrollbars unnecessary properties * Add 'ShowSeparators' property to ScrollViewerAssist * Improve ShowSeparators property * Replaced attached property behavior with triggers. * Add fade effect to scrollbars * Adding sample of auto hiding scrollbars to the demo app. Co-authored-by: Kevin Bost <[email protected]>
1 parent da831d0 commit d8e8676

File tree

3 files changed

+186
-11
lines changed

3 files changed

+186
-11
lines changed

MainDemo.Wpf/MainWindow.xaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
Margin="0 0 0 16"
107107
/>
108108
<ScrollViewer Grid.Row="1"
109+
materialDesign:ScrollViewerAssist.IsAutoHideEnabled="True"
109110
HorizontalScrollBarVisibility="{Binding ElementName=DemoItemsListBox, Path=SelectedItem.HorizontalScrollBarVisibilityRequirement}"
110111
VerticalScrollBarVisibility="{Binding ElementName=DemoItemsListBox, Path=SelectedItem.VerticalScrollBarVisibilityRequirement}"
111112
Padding="{Binding ElementName=DemoItemsListBox, Path=SelectedItem.MarginRequirement}">

MaterialDesignThemes.Wpf/ScrollViewerAssist.cs

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33

44
namespace MaterialDesignThemes.Wpf
55
{
6-
internal static class ScrollViewerAssist
6+
public static class ScrollViewerAssist
77
{
8-
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
8+
internal static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.RegisterAttached(
99
"SyncHorizontalOffset", typeof(double), typeof(ScrollViewerAssist), new PropertyMetadata(default(double), OnSyncHorizontalOffsetChanged));
1010

1111
private static void OnSyncHorizontalOffsetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@@ -14,14 +14,54 @@ private static void OnSyncHorizontalOffsetChanged(DependencyObject d, Dependency
1414
scrollViewer?.ScrollToHorizontalOffset((double)e.NewValue);
1515
}
1616

17-
public static void SetSyncHorizontalOffset(DependencyObject element, double value)
17+
internal static void SetSyncHorizontalOffset(DependencyObject element, double value)
1818
{
1919
element.SetValue(HorizontalOffsetProperty, value);
2020
}
2121

22-
public static double GetSyncHorizontalOffset(DependencyObject element)
22+
internal static double GetSyncHorizontalOffset(DependencyObject element)
2323
{
24-
return (double) element.GetValue(HorizontalOffsetProperty);
24+
return (double)element.GetValue(HorizontalOffsetProperty);
2525
}
26+
27+
public static readonly DependencyProperty IsAutoHideEnabledProperty = DependencyProperty.RegisterAttached(
28+
"IsAutoHideEnabled", typeof(bool), typeof(ScrollViewerAssist), new PropertyMetadata(default(bool)));
29+
30+
public static void SetIsAutoHideEnabled(DependencyObject element, bool value)
31+
{
32+
element.SetValue(IsAutoHideEnabledProperty, value);
33+
}
34+
35+
public static bool GetIsAutoHideEnabled(DependencyObject element)
36+
{
37+
return (bool)element.GetValue(IsAutoHideEnabledProperty);
38+
}
39+
40+
public static readonly DependencyProperty CornerRectangleVisibilityProperty = DependencyProperty.RegisterAttached(
41+
"CornerRectangleVisibility", typeof(Visibility), typeof(ScrollViewerAssist), new PropertyMetadata(default(Visibility)));
42+
43+
public static void SetCornerRectangleVisibility(DependencyObject element, Visibility value)
44+
{
45+
element.SetValue(CornerRectangleVisibilityProperty, value);
46+
}
47+
48+
public static Visibility GetCornerRectangleVisibility(DependencyObject element)
49+
{
50+
return (Visibility)element.GetValue(CornerRectangleVisibilityProperty);
51+
}
52+
53+
public static readonly DependencyProperty ShowSeparatorsProperty = DependencyProperty.RegisterAttached(
54+
"ShowSeparators", typeof(bool), typeof(ScrollViewerAssist), new PropertyMetadata(default(bool)));
55+
56+
public static void SetShowSeparators(DependencyObject element, bool value)
57+
{
58+
element.SetValue(ShowSeparatorsProperty, value);
59+
}
60+
61+
public static bool GetShowSeparators(DependencyObject element)
62+
{
63+
return (bool)element.GetValue(ShowSeparatorsProperty);
64+
}
65+
2666
}
2767
}
Lines changed: 140 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:wpf="clr-namespace:MaterialDesignThemes.Wpf">
4+
35
<ControlTemplate x:Key="MaterialDesignScrollViewerTemplate" TargetType="{x:Type ScrollViewer}">
46
<Grid x:Name="Grid" Background="{TemplateBinding Background}">
57
<Grid.ColumnDefinitions>
@@ -10,15 +12,147 @@
1012
<RowDefinition Height="*"/>
1113
<RowDefinition Height="Auto"/>
1214
</Grid.RowDefinitions>
13-
<Rectangle x:Name="Corner" Grid.Column="1" Fill="{DynamicResource MaterialDesignSelection}" Grid.Row="1"/>
14-
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Grid.Column="0" Margin="{TemplateBinding Padding}" Grid.Row="0"/>
15-
<ScrollBar x:Name="PART_VerticalScrollBar" AutomationProperties.AutomationId="VerticalScrollBar" Cursor="Arrow" Grid.Column="1" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Grid.Row="0" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportHeight}" />
16-
<ScrollBar x:Name="PART_HorizontalScrollBar" AutomationProperties.AutomationId="HorizontalScrollBar" Cursor="Arrow" Grid.Column="0" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Orientation="Horizontal" Grid.Row="1" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" ViewportSize="{TemplateBinding ViewportWidth}" />
15+
16+
<Rectangle
17+
x:Name="PART_Corner"
18+
Grid.Column="1"
19+
Fill="{DynamicResource MaterialDesignSelection}"
20+
Grid.Row="1"
21+
Visibility="{Binding Path=(wpf:ScrollViewerAssist.CornerRectangleVisibility), RelativeSource={RelativeSource TemplatedParent}}"/>
22+
23+
<Separator
24+
x:Name="PART_TopSeparator"
25+
Background="{DynamicResource MaterialDesignSelection}"
26+
Grid.Column="0"
27+
Grid.Row="0"
28+
Opacity="0.4"
29+
Margin="0"
30+
VerticalAlignment="Top"
31+
Visibility="Hidden"/>
32+
33+
<ScrollContentPresenter
34+
x:Name="PART_ScrollContentPresenter"
35+
CanContentScroll="{TemplateBinding CanContentScroll}"
36+
CanHorizontallyScroll="False" CanVerticallyScroll="False"
37+
ContentTemplate="{TemplateBinding ContentTemplate}"
38+
Content="{TemplateBinding Content}"
39+
Grid.Column="0"
40+
Margin="{TemplateBinding Padding}"
41+
Grid.Row="0"/>
42+
43+
<Separator
44+
x:Name="PART_BottomSeparator"
45+
Background="{DynamicResource MaterialDesignSelection}"
46+
Grid.Column="0"
47+
Grid.Row="0"
48+
Opacity="0.4"
49+
Margin="0"
50+
VerticalAlignment="Bottom"
51+
Visibility="Hidden"/>
52+
53+
<ScrollBar
54+
x:Name="PART_VerticalScrollBar"
55+
AutomationProperties.AutomationId="VerticalScrollBar"
56+
Grid.Column="1"
57+
Maximum="{TemplateBinding ScrollableHeight}"
58+
Minimum="0"
59+
Grid.Row="0"
60+
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"
61+
Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
62+
ViewportSize="{TemplateBinding ViewportHeight}" />
63+
64+
<ScrollBar
65+
x:Name="PART_HorizontalScrollBar"
66+
AutomationProperties.AutomationId="HorizontalScrollBar"
67+
Grid.Column="0"
68+
Maximum="{TemplateBinding ScrollableWidth}"
69+
Minimum="0"
70+
Orientation="Horizontal"
71+
Grid.Row="1"
72+
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"
73+
Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}"
74+
ViewportSize="{TemplateBinding ViewportWidth}" />
1775
</Grid>
76+
<ControlTemplate.Triggers>
77+
<MultiTrigger>
78+
<MultiTrigger.Conditions>
79+
<Condition Property="wpf:ScrollViewerAssist.ShowSeparators" Value="True" />
80+
<Condition Property="ComputedVerticalScrollBarVisibility" Value="Visible" />
81+
</MultiTrigger.Conditions>
82+
<Setter TargetName="PART_BottomSeparator" Property="Visibility" Value="Visible"/>
83+
</MultiTrigger>
84+
85+
<Trigger Property="VerticalOffset" Value="0">
86+
<Setter TargetName="PART_TopSeparator" Property="Visibility" Value="Hidden" />
87+
</Trigger>
88+
89+
<Trigger Property="wpf:ScrollViewerAssist.ShowSeparators" Value="False">
90+
<Setter TargetName="PART_TopSeparator" Property="Visibility" Value="Hidden" />
91+
</Trigger>
92+
93+
<MultiTrigger>
94+
<MultiTrigger.Conditions>
95+
<Condition Property="wpf:ScrollViewerAssist.IsAutoHideEnabled" Value="True" />
96+
<Condition Property="ComputedVerticalScrollBarVisibility" Value="Visible" />
97+
<Condition Property="IsMouseOver" Value="False" />
98+
</MultiTrigger.Conditions>
99+
<MultiTrigger.EnterActions>
100+
<BeginStoryboard>
101+
<Storyboard>
102+
<DoubleAnimation
103+
To="0"
104+
Duration="0:0:0.2"
105+
Storyboard.TargetProperty="Opacity"
106+
Storyboard.TargetName="PART_VerticalScrollBar"/>
107+
</Storyboard>
108+
</BeginStoryboard>
109+
</MultiTrigger.EnterActions>
110+
<MultiTrigger.ExitActions>
111+
<BeginStoryboard>
112+
<Storyboard>
113+
<DoubleAnimation
114+
To="1"
115+
Duration="0:0:0.2"
116+
Storyboard.TargetProperty="Opacity"
117+
Storyboard.TargetName="PART_VerticalScrollBar"/>
118+
</Storyboard>
119+
</BeginStoryboard>
120+
</MultiTrigger.ExitActions>
121+
</MultiTrigger>
122+
123+
<MultiTrigger>
124+
<MultiTrigger.Conditions>
125+
<Condition Property="wpf:ScrollViewerAssist.IsAutoHideEnabled" Value="True" />
126+
<Condition Property="ComputedHorizontalScrollBarVisibility" Value="Visible" />
127+
<Condition Property="IsMouseOver" Value="False" />
128+
</MultiTrigger.Conditions>
129+
<MultiTrigger.EnterActions>
130+
<BeginStoryboard>
131+
<Storyboard>
132+
<DoubleAnimation
133+
To="0"
134+
Duration="0:0:0.2"
135+
Storyboard.TargetProperty="Opacity"
136+
Storyboard.TargetName="PART_HorizontalScrollBar"/>
137+
</Storyboard>
138+
</BeginStoryboard>
139+
</MultiTrigger.EnterActions>
140+
<MultiTrigger.ExitActions>
141+
<BeginStoryboard>
142+
<Storyboard>
143+
<DoubleAnimation
144+
To="1"
145+
Duration="0:0:0.2"
146+
Storyboard.TargetProperty="Opacity"
147+
Storyboard.TargetName="PART_HorizontalScrollBar"/>
148+
</Storyboard>
149+
</BeginStoryboard>
150+
</MultiTrigger.ExitActions>
151+
</MultiTrigger>
152+
</ControlTemplate.Triggers>
18153
</ControlTemplate>
19154

20155
<Style TargetType="ScrollViewer" x:Key="MaterialDesignScrollViewer">
21156
<Setter Property="Template" Value="{StaticResource MaterialDesignScrollViewerTemplate}" />
22157
</Style>
23-
24158
</ResourceDictionary>

0 commit comments

Comments
 (0)