/// <summary> /// Uses Composition API to get the UIElement and sets an ExpressionAnimation /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header /// is entirely scrolled off. /// </summary> /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns> private bool AssignAnimation() { StopAnimation(); if (AssociatedObject == null) { return(false); } if (_scrollViewer == null) { _scrollViewer = AssociatedObject as ScrollViewer ?? AssociatedObject.FindDescendant <ScrollViewer>(); } if (_scrollViewer == null) { return(false); } var listView = AssociatedObject as Windows.UI.Xaml.Controls.ListViewBase ?? AssociatedObject.FindDescendant <Windows.UI.Xaml.Controls.ListViewBase>(); if (listView != null && listView.ItemsPanelRoot != null) { Canvas.SetZIndex(listView.ItemsPanelRoot, -1); } if (_scrollProperties == null) { _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollViewer); } if (_scrollProperties == null) { return(false); } // Implicit operation: Find the Header object of the control if it uses ListViewBase if (HeaderElement == null && listView != null) { HeaderElement = listView.Header as UIElement; } var headerElement = HeaderElement as FrameworkElement; if (headerElement == null || headerElement.RenderSize.Height == 0) { return(false); } if (_headerVisual == null) { _headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); } if (_headerVisual == null) { return(false); } _scrollViewer.ViewChanged -= ScrollViewer_ViewChanged; _scrollViewer.ViewChanged += ScrollViewer_ViewChanged; _scrollViewer.GotFocus -= ScrollViewer_GotFocus; _scrollViewer.GotFocus += ScrollViewer_GotFocus; headerElement.SizeChanged -= ScrollHeader_SizeChanged; headerElement.SizeChanged += ScrollHeader_SizeChanged; var compositor = _scrollProperties.Compositor; if (_animationProperties == null) { _animationProperties = compositor.CreatePropertySet(); _animationProperties.InsertScalar("OffsetY", 0.0f); } var propSetOffset = _animationProperties.GetReference().GetScalarProperty("OffsetY"); var scrollPropSet = _scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var expressionAnimation = ExpressionFunctions.Max(ExpressionFunctions.Min(propSetOffset, -scrollPropSet.Translation.Y), 0); _headerVisual.StartAnimation("Offset.Y", expressionAnimation); return(true); }
/// <summary> /// Uses Composition API to get the UIElement and sets an ExpressionAnimation /// The ExpressionAnimation uses the height of the UIElement to calculate an opacity value /// for the Header as it is scrolling off-screen. The opacity reaches 0 when the Header /// is entirely scrolled off. /// </summary> /// <returns><c>true</c> if the assignment was successful; otherwise, <c>false</c>.</returns> private bool AssignAnimation() { StopAnimation(); // Confirm that Windows.UI.Xaml.Hosting.ElementCompositionPreview is available (Windows 10 10586 or later). if (!ApiInformation.IsMethodPresent("Windows.UI.Xaml.Hosting.ElementCompositionPreview", nameof(ElementCompositionPreview.GetScrollViewerManipulationPropertySet))) { // Just return true since it's not supported return(true); } if (AssociatedObject == null) { return(false); } if (_scrollViewer == null) { _scrollViewer = AssociatedObject as ScrollViewer ?? AssociatedObject.FindDescendant <ScrollViewer>(); } if (_scrollViewer == null) { return(false); } if (_scrollProperties == null) { _scrollProperties = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(_scrollViewer); } if (_scrollProperties == null) { return(false); } // Implicit operation: Find the Header object of the control if it uses ListViewBase if (HeaderElement == null) { var listElement = AssociatedObject as Windows.UI.Xaml.Controls.ListViewBase ?? AssociatedObject.FindDescendant <Windows.UI.Xaml.Controls.ListViewBase>(); if (listElement != null) { HeaderElement = listElement.Header as UIElement; } } var headerElement = HeaderElement as FrameworkElement; if (headerElement == null || headerElement.RenderSize.Height == 0) { return(false); } if (_headerVisual == null) { _headerVisual = ElementCompositionPreview.GetElementVisual(headerElement); } if (_headerVisual == null) { return(false); } _scrollViewer.ViewChanged -= ScrollViewer_ViewChanged; _scrollViewer.ViewChanged += ScrollViewer_ViewChanged; _scrollViewer.GotFocus -= ScrollViewer_GotFocus; _scrollViewer.GotFocus += ScrollViewer_GotFocus; headerElement.SizeChanged -= ScrollHeader_SizeChanged; headerElement.SizeChanged += ScrollHeader_SizeChanged; var compositor = _scrollProperties.Compositor; if (_animationProperties == null) { _animationProperties = compositor.CreatePropertySet(); _animationProperties.InsertScalar("OffsetY", 0.0f); } var propSetOffset = _animationProperties.GetReference().GetScalarProperty("OffsetY"); var scrollPropSet = _scrollProperties.GetSpecializedReference <ManipulationPropertySetReferenceNode>(); var expressionAnimation = ExpressionFunctions.Max(ExpressionFunctions.Min(propSetOffset, -scrollPropSet.Translation.Y), 0); _headerVisual.StartAnimation("Offset.Y", expressionAnimation); return(true); }