滚动时保持元素在视图中 [英] Keep element in view while scrolling

查看:66
本文介绍了滚动时保持元素在视图中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

简单的问题,我有一个 Windows Phone 页面,其中包含一个 scrollviewer,里面有一个 image、一个 textblock 和一个 富文本框.

Simpel question, I have a windows phone page that contains a scrollviewer with inside it an image, a textblock and a richtextbox.

现在,当用户开始滚动时,我希望 textblockimage 滚动到页面外时保持在顶部.

Now when the user starts scrolling I want to keep the textblock in view on top when the image has scrolled outside the page.

所以效果是,用户开始向上滚动,一切都向上滚动,当图像在页面之外时,文本块停留在页面顶部,而富文本框继续向上滚动.

So the effect is, user starts scrolling upwards, everything scrolls upwards, when the image is outside the page, the textblock stays at the top of the page but the richtextbox keeps scrolling upwards.

有什么想法吗?

推荐答案

以下是达到此结果的方法:

Here is a way to reach this result:

首先是布局.我已经设置了一个网格,有两行.第一个是空的,当我们需要冻结它时将托管标头.第二行包含滚动查看器.

First, the layout. I've set a grid, with two rows. The first is empty, and will host the header when we need to freeze it. The second row contains the scrollviewer.

在滚动查看器中,我将控件放在一个网格中,但您可以使用任何适合您的容器.

Inside the scrollviewer, I've put the controls in a grid, but you can use whatever container suits you.

<ScrollViewer Grid.Row="1"
                Margin="0"
                Padding="0"
                x:Name="ParentScroll"
                ManipulationMode="Control"
                MouseMove="ParentScroll_MouseMove">
    <Grid x:Name="ChildGrid">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition />
        </Grid.RowDefinitions>

        <Image Source="Picture.jpg" Grid.Row="0"/>
        <TextBlock Text="Header" Grid.Row="1" x:Name="TextHeader" />
        <RichTextBox Grid.Row="2" x:Name="RichText">
            <Paragraph>
                <Bold>RichTextBox</Bold>
                <!-- More stuff -->
            </Paragraph>
        </RichTextBox>
    </Grid>
</ScrollViewer>

我使用 MouseMove 事件来通知滚动事件.您还可以深入研究模板,提取 ScrollBar 控件,并订阅 ValueChanged 事件,如下所述:http://social.msdn.microsoft.com/Forums/wpapps/en-US/81fcd34e-6ec9-48d0-891e-c53a53344553/scrollviewer-synchronization

I use the MouseMove event to be notified of the scrolling event. You can also dig into the template, extract the ScrollBar control, and subscribe to the ValueChanged event, as described here: http://social.msdn.microsoft.com/Forums/wpapps/en-US/81fcd34e-6ec9-48d0-891e-c53a53344553/scrollviewer-synchronization

请注意,您需要将ManipulationMode 设置为Control,否则控件的位置将不会以平滑的速度更新.我猜是因为一些内部优化.

Note that you need to set ManipulationMode to Control or the position of the controls won't be updated at a smooth rate. I guess it's due to some internal optimization.

在后面的代码中,我使用了 TransformToVisual 方法来计算控件与 ScrollViewer 的相对位置.这样,我可以知道标题何时消失.当它发生时,我将它从子网格中删除,并将其放在 ScrollViewer 之外的父网格中.当 RichTextBox 顶部消失时,我将标题放回 ScrollViewer:

In the code behind, I use the TransformToVisual method to compute the relative position of the controls to the ScrollViewer. This way, I can know when the header goes out of view. When it does, I remove it from the child grid, and put it outside of the ScrollViewer, in the parent grid. When the top of the RichTextBox goes out of view, I put the header back into the ScrollViewer:

private void ParentScroll_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
    if (Grid.GetRow(this.TextHeader) == 1)
    {
        var generalTransform = TextHeader.TransformToVisual(ParentScroll);
        var childToParentCoordinates = generalTransform.Transform(new Point(0, 0));

        if (childToParentCoordinates.Y < 0)
        {
            this.ChildGrid.Children.Remove(this.TextHeader);
            this.ParentGrid.Children.Add(this.TextHeader);

            Grid.SetRow(this.TextHeader, 0);
        }
    }
    else
    {
        var generalTransform = RichText.TransformToVisual(ParentScroll);
        var childToParentCoordinates = generalTransform.Transform(new Point(0, 0));

        if (childToParentCoordinates.Y > 0)
        {
            this.ParentGrid.Children.Remove(this.TextHeader);
            this.ChildGrid.Children.Add(this.TextHeader);

            Grid.SetRow(this.TextHeader, 1);
        }
    }

可能有更简单的方法可以达到相同的结果,但此解决方案似乎在模拟器中运行顺畅.

There may be less-hacky ways to reach the same results, but this solution seems to work smoothly in the emulator.

这篇关于滚动时保持元素在视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆