Skip to content

Commit

Permalink
Add GoToTop
Browse files Browse the repository at this point in the history
  • Loading branch information
ghost1372 committed Jan 2, 2025
1 parent 95ff89c commit e0739f1
Show file tree
Hide file tree
Showing 11 changed files with 420 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ Install-Package DevWinUI
## 🔥 DevWinUI.Controls 🔥
### ⚡ What’s Inside? ⚡

- ✨ GoToTop
- ✨ FlexPanel
- ✨ HoneycombPanel
- ✨ ElementGroup
Expand Down Expand Up @@ -260,6 +261,9 @@ Install-Package DevWinUI.ContextMenu

## 🕰️ History 🕰️

### GoToTop
![DevWinUI](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/GoToTop.gif)

### FlexPanel
![DevWinUI](https://raw.githubusercontent.com/ghost1372/DevWinUI-Resources/refs/heads/main/DevWinUI-Docs/FlexPanel.gif)

Expand Down
121 changes: 121 additions & 0 deletions dev/DevWinUI.Controls/Controls/Others/GotoTop.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
namespace DevWinUI;
public partial class GotoTop : Button
{
private Action _gotoTopAction;

private ScrollViewer _scrollViewer;
private ScrollView _scrollView;

public static readonly DependencyProperty TargetProperty = DependencyProperty.Register(
nameof(Target), typeof(DependencyObject), typeof(GotoTop), new PropertyMetadata(null, OnTargetChanged));

public DependencyObject Target
{
get => (DependencyObject)GetValue(TargetProperty);
set => SetValue(TargetProperty, value);
}

public static readonly DependencyProperty AnimatedProperty = DependencyProperty.Register(
nameof(Animated), typeof(bool), typeof(GotoTop), new PropertyMetadata(true));

public bool Animated
{
get => (bool)GetValue(AnimatedProperty);
set => SetValue(AnimatedProperty, value);
}

public static readonly DependencyProperty HidingHeightProperty = DependencyProperty.Register(
nameof(HidingHeight), typeof(double), typeof(GotoTop), new PropertyMetadata(0.0));

public double HidingHeight
{
get => (double)GetValue(HidingHeightProperty);
set => SetValue(HidingHeightProperty, value);
}

public static readonly DependencyProperty AutoHidingProperty = DependencyProperty.Register(
nameof(AutoHiding), typeof(bool), typeof(GotoTop), new PropertyMetadata(true));

public bool AutoHiding
{
get => (bool)GetValue(AutoHidingProperty);
set => SetValue(AutoHidingProperty, value);
}

public GotoTop()
{
Loaded += (s, e) => CreateGotoAction(Target);
Click -= GotoTop_Click;
Click += GotoTop_Click;
}

private void GotoTop_Click(object sender, RoutedEventArgs e)
{
_gotoTopAction?.Invoke();
}

private static void OnTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (d is GotoTop gotoTop)
{
gotoTop.CreateGotoAction(e.NewValue as DependencyObject);
}
}

public virtual void CreateGotoAction(DependencyObject obj)
{
if (_scrollViewer != null)
{
_scrollViewer.ViewChanged -= ScrollViewer_ViewChanged;
}
if (_scrollView != null)
{
_scrollView.ViewChanged -= ScrollView_ViewChanged;
}

if (obj is ScrollViewer viewer && viewer != null)
{
_scrollViewer = viewer;
_scrollViewer.ViewChanged += ScrollViewer_ViewChanged;

if (Animated)
{
_gotoTopAction = () => _scrollViewer.ChangeView(null, 0, null, false);
}
else
{
_gotoTopAction = () => _scrollViewer.ChangeView(null, 0, null, true);
}
}
else if (obj is ScrollView view && view != null)
{
_scrollView = view;
_scrollView.ViewChanged += ScrollView_ViewChanged;

if (Animated)
{
_gotoTopAction = () => _scrollView?.ScrollTo(0, 0, new ScrollingScrollOptions(ScrollingAnimationMode.Auto));
}
else
{
_gotoTopAction = () => _scrollView?.ScrollTo(0, 0, new ScrollingScrollOptions(ScrollingAnimationMode.Disabled));
}
}
}

private void ScrollView_ViewChanged(ScrollView sender, object args)
{
if (AutoHiding)
{
Visibility = sender.VerticalOffset > HidingHeight ? Visibility.Visible : Visibility.Collapsed;
}
}

private void ScrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (AutoHiding)
{
Visibility = _scrollViewer.VerticalOffset > HidingHeight ? Visibility.Visible : Visibility.Collapsed;
}
}
}
73 changes: 73 additions & 0 deletions dev/DevWinUI.Controls/Themes/Generic.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ Themes\Styles\Controls\DateTimePicker.xaml
Themes\Styles\Controls\Divider.xaml
Themes\Styles\Controls\FlipSide.xaml
Themes\Styles\Controls\FlyoutMenuButton.xaml
Themes\Styles\Controls\GoToTop.xaml
Themes\Styles\Controls\Gravatar.xaml
Themes\Styles\Controls\Growl.xaml
Themes\Styles\Controls\ImageEx.xaml
Expand Down Expand Up @@ -4184,6 +4185,78 @@ Themes\Styles\Win2D\Watermark.xaml
</Setter.Value>
</Setter>
</Style>
<Style BasedOn="{StaticResource DefaultButtonStyle}" TargetType="local:GotoTop">
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="CornerRadius" Value="90" />
<Setter Property="ToolTipService.ToolTip" Value="Go To Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter x:Name="ContentPresenter" Padding="{TemplateBinding Padding}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" AnimatedIcon.State="Normal" AutomationProperties.AccessibilityView="Raw" Background="{TemplateBinding Background}" BackgroundSizing="{TemplateBinding BackgroundSizing}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" CornerRadius="{TemplateBinding CornerRadius}" Foreground="{TemplateBinding Foreground}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<FontIcon Glyph="" />
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:Growl">
<Setter Property="IsOpen" Value="True" />
<Setter Property="CornerRadius" Value="{ThemeResource OverlayCornerRadius}" />
Expand Down
110 changes: 110 additions & 0 deletions dev/DevWinUI.Controls/Themes/Styles/Controls/GoToTop.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="utf-8" ?>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DevWinUI">

<Style BasedOn="{StaticResource DefaultButtonStyle}"
TargetType="local:GotoTop">
<Setter Property="Width" Value="50" />
<Setter Property="Height" Value="50" />
<Setter Property="CornerRadius" Value="90" />
<Setter Property="ToolTipService.ToolTip" Value="Go To Top" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="Normal"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}"
Foreground="{TemplateBinding Foreground}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<FontIcon Glyph="&#xE70e;" />
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Binary file added dev/DevWinUI.Gallery/Assets/Fluent/ScrollView.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions dev/DevWinUI.Gallery/Assets/NavViewMenu/AppData.json
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@
"ImagePath": "ms-appx:///Assets/Fluent/RatingControl.png",
"IsSpecialSection": false,
"Items": [
{
"UniqueId": "DevWinUIGallery.Views.GoToTopPage",
"Title": "GoToTop",
"Subtitle": "GoToTop",
"IsNew": true,
"ImagePath": "ms-appx:///Assets/Fluent/ScrollView.png"
},
{
"UniqueId": "DevWinUIGallery.Views.FlexPanelPage",
"Title": "FlexPanel",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<ScrollViewer Name="ScrollViewerSample">
<Border Height="2000" Margin="8,0">
<Border.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="White" Offset="0"/>
<GradientStop Color="Black" Offset="1"/>
</LinearGradientBrush>
</Border.Background>
</Border>
</ScrollViewer>
<dev:GotoTop Animated="True" AutoHiding="True" Target="{Binding ElementName=ScrollViewerSample}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,20,20"/>
Loading

0 comments on commit e0739f1

Please sign in to comment.