33// See the LICENSE file in the project root for more information.
44
55using CommunityToolkit . WinUI . Animations . Expressions ;
6+ using CommunityToolkit . WinUI . Behaviors . Internal ;
67
78#if WINUI3
89using Microsoft . UI . Composition ;
@@ -22,134 +23,35 @@ namespace CommunityToolkit.WinUI.Behaviors;
2223/// <seealso>
2324/// <cref>Microsoft.Xaml.Interactivity.Behavior{Windows.UI.Xaml.UIElement}</cref>
2425/// </seealso>
25- public class FadeHeaderBehavior : BehaviorBase < FrameworkElement >
26+ public class FadeHeaderBehavior : HeaderBehaviorBase
2627{
27- /// <summary>
28- /// Attaches the behavior to the associated object.
29- /// </summary>
30- /// <returns>
31- /// <c>true</c> if attaching succeeded; otherwise <c>false</c>.
32- /// </returns>
33- protected override bool Initialize ( )
28+ /// <inheritdoc/>
29+ protected override bool AssignAnimation ( )
3430 {
35- var result = AssignFadeAnimation ( ) ;
36- return result ;
37- }
38-
39- /// <summary>
40- /// Detaches the behavior from the associated object.
41- /// </summary>
42- /// <returns>
43- /// <c>true</c> if detaching succeeded; otherwise <c>false</c>.
44- /// </returns>
45- protected override bool Uninitialize ( )
46- {
47- RemoveFadeAnimation ( ) ;
48- return true ;
49- }
50-
51- /// <summary>
52- /// If any of the properties are changed then the animation is automatically started depending on the AutomaticallyStart property.
53- /// </summary>
54- /// <param name="d">The dependency object.</param>
55- /// <param name="e">The <see cref="DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
56- private static void PropertyChangedCallback ( DependencyObject d , DependencyPropertyChangedEventArgs e )
57- {
58- var b = d as FadeHeaderBehavior ;
59- b ? . AssignFadeAnimation ( ) ;
60- }
61-
62- /// <summary>
63- /// The UIElement that will be faded.
64- /// </summary>
65- public static readonly DependencyProperty HeaderElementProperty = DependencyProperty . Register (
66- nameof ( HeaderElement ) , typeof ( UIElement ) , typeof ( FadeHeaderBehavior ) , new PropertyMetadata ( null , PropertyChangedCallback ) ) ;
67-
68- /// <summary>
69- /// Gets or sets the target element for the Fading behavior.
70- /// </summary>
71- /// <remarks>
72- /// Set this using the header of a ListView or GridView. You can use the entire root of the header or an element within the header.
73- ///
74- /// Using this example Header:
75- /// <ListView.Header>
76- /// <Grid Name="MyHeader">
77- /// </Grid>
78- /// </ListView.Header>
79- ///
80- /// The behavior would be implemented like this
81- /// <FadeHeaderBehavior HeaderElement="{Binding ElementName=HeaderPanel}" />
82- /// </remarks>
83- public UIElement HeaderElement
84- {
85- get { return ( UIElement ) GetValue ( HeaderElementProperty ) ; }
86- set { SetValue ( HeaderElementProperty , value ) ; }
87- }
88-
89- /// <summary>
90- /// Uses Composition API to get the UIElement and sets an ExpressionAnimation
91- /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value
92- /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header
93- /// is entirely scrolled off.
94- /// </summary>
95- /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns>
96- private bool AssignFadeAnimation ( )
97- {
98- if ( AssociatedObject == null )
31+ if ( base . AssignAnimation ( ) )
9932 {
100- return false ;
101- }
33+ // Get the ScrollViewer's ManipulationPropertySet
34+ var scrollPropSet = _scrollProperties ! . GetSpecializedReference < ManipulationPropertySetReferenceNode > ( ) ;
10235
103- var scroller = AssociatedObject as ScrollViewer ?? AssociatedObject . FindDescendant < ScrollViewer > ( ) ;
104- if ( scroller == null )
105- {
106- return false ;
107- }
36+ // Use the ScrollViewer's Y offset and the header's height to calculate the opacity percentage. Clamp it between 0% and 100%
37+ var headerHeight = ( float ) HeaderElement . RenderSize . Height ;
38+ var opacityExpression = ExpressionFunctions . Clamp ( 1 - ( - scrollPropSet . Translation . Y / headerHeight ) , 0 , 1 ) ;
10839
109- var listView = AssociatedObject as ListViewBase ?? AssociatedObject . FindDescendant < ListViewBase > ( ) ;
40+ // Begin animating
41+ _headerVisual ? . StartAnimation ( "Opacity" , opacityExpression ) ;
11042
111- if ( listView != null && listView . ItemsPanelRoot != null )
112- {
113- Canvas . SetZIndex ( listView . ItemsPanelRoot , - 1 ) ;
114- }
115-
116- // Implicit operation: Find the Header object of the control if it uses ListViewBase
117- if ( HeaderElement == null && listView != null )
118- {
119- HeaderElement = ( listView . Header as UIElement ) ! ;
43+ return true ;
12044 }
12145
122- // If no header is set or detected, return.
123- if ( HeaderElement == null || HeaderElement . RenderSize . Height == 0d )
124- {
125- return false ;
126- }
127-
128- // Get the ScrollViewer's ManipulationPropertySet
129- var scrollViewerManipulationPropSet = ElementCompositionPreview . GetScrollViewerManipulationPropertySet ( scroller ) ;
130- var scrollPropSet = scrollViewerManipulationPropSet . GetSpecializedReference < ManipulationPropertySetReferenceNode > ( ) ;
131-
132- // Use the ScrollViewer's Y offset and the header's height to calculate the opacity percentage. Clamp it between 0% and 100%
133- var headerHeight = ( float ) HeaderElement . RenderSize . Height ;
134- var opacityExpression = ExpressionFunctions . Clamp ( 1 - ( - scrollPropSet . Translation . Y / headerHeight ) , 0 , 1 ) ;
135-
136- // Begin animating
137- var targetElement = ElementCompositionPreview . GetElementVisual ( HeaderElement ) ;
138- targetElement . StartAnimation ( "Opacity" , opacityExpression ) ;
139-
140- return true ;
46+ return false ;
14147 }
14248
143- /// <summary>
144- /// Remove the opacity animation from the UIElement.
145- /// </summary>
146- private void RemoveFadeAnimation ( )
49+ protected override void StopAnimation ( )
14750 {
148- if ( HeaderElement != null )
51+ if ( _headerVisual != null )
14952 {
150- var targetElement = ElementCompositionPreview . GetElementVisual ( HeaderElement ) ;
151- targetElement . StopAnimation ( "Opacity" ) ;
152- targetElement . Opacity = 1.0f ;
53+ _headerVisual . StopAnimation ( "Opacity" ) ;
54+ _headerVisual . Opacity = 1.0f ;
15355 }
15456 }
15557}
0 commit comments