locked
WPF - Shy header RRS feed

  • Question

  • Hi,
    I needed some advice. I'm trying to create a scrollviewer in the WPF, which has a header and when scrolling, the height of the header changes or increases and the elements inside the header. Something similar in the "Shy header  in UWP, see the picture.

    Thanks for advice.


    source code UWP

    <ScrollViewer x:Name="MyScrollviewer" Grid.Row="1" Padding="0,0,0,0">
                    <Grid>
                        <Grid Grid.Row="1" x:Name="SquareGrid" Margin="0,300,0,0">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="Auto"/>
                            </Grid.RowDefinitions>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <Image Source="ms-appx:///Assets/Photos/pic00.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic01.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic02.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic03.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic04.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic05.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic06.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic07.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic08.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic09.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="1" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic10.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic11.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic12.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic13.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic14.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="2" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic15.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic16.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic17.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic18.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic19.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="3" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic20.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic21.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="4" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic22.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="4" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic23.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="4" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic24.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="4" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic25.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="5" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic26.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="5" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic27.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="5" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic28.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="5" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic29.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="5" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic30.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic31.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic32.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic33.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic34.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="6" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                            <Image Source="ms-appx:///Assets/Photos/pic35.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="7" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic36.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="7" Grid.Column="1" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic37.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="7" Grid.Column="2" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic38.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="7" Grid.Column="3" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
                            <Image Source="ms-appx:///Assets/Photos/pic39.jpg" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="7" Grid.Column="4" Width="200" Height="200" Stretch="UniformToFill" Margin="5"/>
    
                        </Grid>
                        <Grid x:Name="Header" Height="300" VerticalAlignment="Top">
                            <ScrollViewer>
                                <Grid>
                                    <Rectangle x:Name="BackgroundRectangle" Width="1050" Height="300" HorizontalAlignment="Left" VerticalAlignment="Top" >
                                        <Rectangle.Fill>
                                            <ImageBrush x:Name="BackgroundImage" ImageSource="ms-appx:///Assets/Photos/no_border_pic27.jpg" Stretch="UniformToFill" Opacity="0.6"/>
                                        </Rectangle.Fill>
                                    </Rectangle>
                                    <Rectangle x:Name="OverlayRectangle" Fill="#BFCFB5C0" Width="1050" Height="300" HorizontalAlignment="Left" VerticalAlignment="Top"/>
                                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top" x:Name="TextContainer">
                                        <Ellipse x:Name="ProfileImage" Height="150" Width="150" Margin="20,70,20,20">
                                            <Ellipse.Fill>
                                                <ImageBrush ImageSource="ms-appx:///Assets/Photos/no_border_pic27.jpg" Stretch="UniformToFill"/>
                                            </Ellipse.Fill>
                                        </Ellipse>
                                        <StackPanel Orientation="Vertical" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,70,0,0">
                                            <TextBlock x:Name="TitleBlock" Text="Lorem Ipsum" Foreground="White" FontSize="20"/>
                                            <TextBlock x:Name="SubtitleBlock" Text="dolor sit amet" Foreground="White" FontSize="10" Margin="0,10,0,0"/>
                                            <TextBlock x:Name="Blurb" Foreground="White" FontSize="12" Width="400" TextWrapping="Wrap" Margin="0,20,0,0">
                                                    <Run>
                                                        Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor 
                                                        incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud 
                                                        exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
                                                    </Run>
                                            </TextBlock>
                                            <TextBlock x:Name="MoreText" Text="More" Foreground="White" Margin="0,10,0,0"/>
                                            <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" Margin="0,10,0,0">
                                                <StackPanel Orientation="Horizontal" x:Name="ButtonPanel">
                                                    <Button Padding="0" Foreground="White" Style="{ThemeResource TextBlockButtonStyle}">
                                                        <StackPanel Orientation="Horizontal">
                                                            <SymbolIcon Symbol="Play"/>
                                                            <TextBlock Text="Play" Margin="10,0,0,0"/>
                                                        </StackPanel>
                                                    </Button>
                                                    <Button Padding="0" Foreground="White" Style="{ThemeResource TextBlockButtonStyle}">
                                                        <StackPanel Orientation="Horizontal" Margin="20,0,0,0">
                                                            <SymbolIcon Symbol="Add"/>
                                                            <TextBlock Text="Add" Margin="10,0,0,0"/>
                                                        </StackPanel>
                                                    </Button>
                                                    <Button Padding="0" Foreground="White" Style="{ThemeResource TextBlockButtonStyle}">
                                                        <StackPanel Orientation="Horizontal" Margin="20,0,0,0">
                                                            <SymbolIcon Symbol="More"/>
                                                        </StackPanel>
                                                    </Button>
                                                </StackPanel>
                                            </StackPanel>
                                        </StackPanel>
                                    </StackPanel>
                                </Grid>
                            </ScrollViewer>
                        </Grid>
                    </Grid>
                </ScrollViewer>
            </Grid>
        </Grid>


    public sealed partial class Detail1Page : Page, INotifyPropertyChanged
        {
            CompositionPropertySet _props;
            CompositionPropertySet _scrollerPropertySet;
            Compositor _compositor;
            private SpriteVisual _blurredBackgroundImageVisual;
    
            public Detail1Page()
            {
                InitializeComponent();
                this.Loaded += Detail1Page_Loaded;
            }
    
            protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
            {
                ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("Image", ProfileImage);
                base.OnNavigatingFrom(e);
            }
                  
            private void Detail1Page_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e)
            {
                var animation = ConnectedAnimationService.GetForCurrentView().GetAnimation("Image");
                if (animation != null)
                {
                    animation.TryStart(ProfileImage);
                }
    
                // Get the PropertySet that contains the scroll values from MyScrollViewer
                _scrollerPropertySet = ElementCompositionPreview.GetScrollViewerManipulationPropertySet(MyScrollviewer);
                _compositor = _scrollerPropertySet.Compositor;
    
                // Create a PropertySet that has values to be referenced in the ExpressionAnimations below
                _props = _compositor.CreatePropertySet();
                _props.InsertScalar("progress", 0);
                _props.InsertScalar("clampSize", 150);
                _props.InsertScalar("scaleFactor", 0.7f);
    
                // Get references to our property sets for use with ExpressionNodes
                var scrollingProperties = _scrollerPropertySet.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
                var props = _props.GetReference();
                var progressNode = props.GetScalarProperty("progress");
                var clampSizeNode = props.GetScalarProperty("clampSize");
                var scaleFactorNode = props.GetScalarProperty("scaleFactor");
    
                // Create a blur effect to be animated based on scroll position
                var blurEffect = new GaussianBlurEffect()
                {
                    Name = "blur",
                    BlurAmount = 0.0f,
                    BorderMode = EffectBorderMode.Hard,
                    Optimization = EffectOptimization.Balanced,
                    Source = new CompositionEffectSourceParameter("source")
                };
    
                var blurBrush = _compositor.CreateEffectFactory(
                    blurEffect,
                    new[] { "blur.BlurAmount" })
                    .CreateBrush();
    
                blurBrush.SetSourceParameter("source", _compositor.CreateBackdropBrush());
    
                // Create a Visual for applying the blur effect
                _blurredBackgroundImageVisual = _compositor.CreateSpriteVisual();
                _blurredBackgroundImageVisual.Brush = blurBrush;
                _blurredBackgroundImageVisual.Size = new Vector2((float)OverlayRectangle.ActualWidth, (float)OverlayRectangle.ActualHeight);
    
                // Insert the blur visual at the right point in the Visual Tree
                ElementCompositionPreview.SetElementChildVisual(OverlayRectangle, _blurredBackgroundImageVisual);
    
                // Create and start an ExpressionAnimation to track scroll progress over the desired distance
                ExpressionNode progressAnimation = EF.Clamp(-scrollingProperties.Translation.Y / clampSizeNode, 0, 1);
                _props.StartAnimation("progress", progressAnimation);
    
                // Create and start an ExpressionAnimation to animate blur radius between 0 and 15 based on progress
                ExpressionNode blurAnimation = EF.Lerp(0, 15, progressNode);
                _blurredBackgroundImageVisual.Brush.Properties.StartAnimation("blur.BlurAmount", blurAnimation);
    
                // Get the backing visual for the header so that its properties can be animated
                Visual headerVisual = ElementCompositionPreview.GetElementVisual(Header);
    
                // Create and start an ExpressionAnimation to clamp the header's offset to keep it onscreen
                ExpressionNode headerTranslationAnimation = EF.Conditional(progressNode < 1, 0, -scrollingProperties.Translation.Y - clampSizeNode);
                headerVisual.StartAnimation("Offset.Y", headerTranslationAnimation);
    
                // Create and start an ExpressionAnimation to scale the header during overpan
                ExpressionNode headerScaleAnimation = EF.Lerp(1, 1.25f, EF.Clamp(scrollingProperties.Translation.Y / 50, 0, 1));
                headerVisual.StartAnimation("Scale.X", headerScaleAnimation);
                headerVisual.StartAnimation("Scale.Y", headerScaleAnimation);
    
                //Set the header's CenterPoint to ensure the overpan scale looks as desired
                headerVisual.CenterPoint = new Vector3((float)(Header.ActualWidth / 2), (float)Header.ActualHeight, 0);
    
                // Get the backing visual for the photo in the header so that its properties can be animated
                Visual photoVisual = ElementCompositionPreview.GetElementVisual(BackgroundRectangle);
    
                // Create and start an ExpressionAnimation to opacity fade out the image behind the header
                ExpressionNode imageOpacityAnimation = 1 - progressNode;
                photoVisual.StartAnimation("opacity", imageOpacityAnimation);
    
                
               // Get the backing visual for the profile picture visual so that its properties can be animated
               Visual profileVisual = ElementCompositionPreview.GetElementVisual(ProfileImage);
    
                // Create and start an ExpressionAnimation to scale the profile image with scroll position
                ExpressionNode scaleAnimation = EF.Lerp(1, scaleFactorNode, progressNode);
                profileVisual.StartAnimation("Scale.X", scaleAnimation);
                profileVisual.StartAnimation("Scale.Y", scaleAnimation);
    
                // Get backing visuals for the text blocks so that their properties can be animated
                Visual blurbVisual = ElementCompositionPreview.GetElementVisual(Blurb);
                Visual subtitleVisual = ElementCompositionPreview.GetElementVisual(SubtitleBlock);
                Visual moreVisual = ElementCompositionPreview.GetElementVisual(MoreText);
    
                // Create an ExpressionAnimation that moves between 1 and 0 with scroll progress, to be used for text block opacity
                ExpressionNode textOpacityAnimation = EF.Clamp(1 - (progressNode * 2), 0, 1);
    
                // Start opacity and scale animations on the text block visuals
                blurbVisual.StartAnimation("Opacity", textOpacityAnimation);
                blurbVisual.StartAnimation("Scale.X", scaleAnimation);
                blurbVisual.StartAnimation("Scale.Y", scaleAnimation);
    
                subtitleVisual.StartAnimation("Opacity", textOpacityAnimation);
                subtitleVisual.StartAnimation("Scale.X", scaleAnimation);
                subtitleVisual.StartAnimation("Scale.Y", scaleAnimation);
    
                moreVisual.StartAnimation("Opacity", textOpacityAnimation);
                moreVisual.StartAnimation("Scale.X", scaleAnimation);
                moreVisual.StartAnimation("Scale.Y", scaleAnimation);
    
                // Get the backing visuals for the text and button containers so that their properites can be animated
                Visual textVisual = ElementCompositionPreview.GetElementVisual(TextContainer);
                Visual buttonVisual = ElementCompositionPreview.GetElementVisual(ButtonPanel);
    
                // When the header stops scrolling it is 150 pixels offscreen.  We want the text header to end up with 50 pixels of its content
                // offscreen which means it needs to go from offset 0 to 100 as we traverse through the scrollable region
                ExpressionNode contentOffsetAnimation = progressNode * 100;
                textVisual.StartAnimation("Offset.Y", contentOffsetAnimation);
    
                ExpressionNode buttonOffsetAnimation = progressNode * -100;
                buttonVisual.StartAnimation("Offset.Y", buttonOffsetAnimation);
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
            {
                if (Equals(storage, value))
                {
                    return;
                }
    
                storage = value;
                OnPropertyChanged(propertyName);
            }
    
            private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
    
        }




    • Edited by ORRNY66 Thursday, October 11, 2018 7:23 PM
    Thursday, October 11, 2018 7:21 PM

All replies

  • Hi ORRNY66,

    I test your xaml code at my side, but I don't have your problem.

    In C# code, you use CompositionPropertySet class, but I find this is UWP API, this is wpf forum, can you post your wpf project code?

    I also find you post same thread in Stackoverflow, if you resolved your issue, please remember to share your solution and close your thread by marking the helpful post as answer, it is beneficial to other community members who face the same issue.

    https://stackoverflow.com/questions/52535538/wpf-shy-header

    Best Regards,

    Cherry


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, October 12, 2018 3:20 AM