如何检测ScrollViewer是否超出其可用范围

时间:2015-08-14 15:19:54

标签: xaml windows-8.1 windows-10

检测ScrollViewer何时处于顶部或底部很容易,但我想检测用户何时拉动ScrollViewer,超过其限制,并在顶部或底部显示一些空间距。你猜对了,我想实现类似于“拉动刷新”的东西。

VerticalOffset不会改变,ViewChanging或ViewChanged事件不会触发,我看不到任何变换对象在子元素上发生变化。我所知道的是,它是ScrollContentPresenter中的ItemsPresenter似乎向下移动。

3 个答案:

答案 0 :(得分:1)

我有一个非常适合Scaling / Zooming的解决方案(拉出去找某个成语)但我不确定如何将它应用到翻译习语(也许是因为我只是厌倦了那一刻)。

我写下来以防有人能找到一种巧妙的方法来为翻译(拉动刷新)问题寻找类似的解决方案。

 // setup code. I do this when I load content into the scroll viewer initially

 myScrollView.MinZoomFactor = desiredMinZoom * 0.4f;
 myScrollView.ZoomSnapPoints.Clear();
 myScrollView.ZoomSnapPoints.Add((float) desiredMinZoom );

// ...

    private void myScrollView_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
    {
        if (e.NextView.ZoomFactor < myScrollView.ZoomSnapPoints.First())
            myScrollView.ZoomSnapPointsType = SnapPointsType.Mandatory;
        else
            myScrollView.ZoomSnapPointsType = SnapPointsType.Optional;

        if ( e.NextView.ZoomFactor == myScrollView.MinZoomFactor )
        {
            VisualStateManager.GoToState(this, "GoSomewhere", true);
            bookView.ZoomToFactor( myScrollView.MinZoomFactor );
        }

    }

此代码的行为就好像MinZoom因子下的任何内容实际上是拉伸画布一样(因为它只是在你松开时快速向后拍摄),但是一旦缩放回到&#34;绿色区域,就会删除强制性捕捉点& #34;

它完全符合人们的需要。

答案 1 :(得分:1)

这是一个没有实现任何自定义类的解决方案,并且几乎没有代码隐藏(如果你真的是代码隐藏的话,你可以将它压缩到单个函数中)。

它与以前发布的ZoomFactor解决方案实现的几乎完全相同。

此代码存在细微之处和局限性。

最重要的是当内部显示的面板小于滚动视图本身时,滚动查看器根本不移动(没有拉伸交互)。这是一个问题,因为它打破了刷新范例,但可以通过填充堆栈面板来解决。

另一个重点是边框尺寸。读者可以测试threshold值未考虑边界时会发生什么。这也是我将这些可怕的边界置于首位的原因,以便可以看到这个问题。

最后一个限制是下拉保证金的大小。它的高度受实际捕捉点距离的限制,这与堆叠面板中的元素有关。在那里有一些游戏要做,但是按照这里设置的工作示例,它不应该是一个太大的交易。

所有这些都说,这是完全正常的下拉刷新代码:

<RelativePanel Background="Gray">
    <ScrollViewer Name="outerScroll"
                  VerticalSnapPointsAlignment="Far"
                  VerticalSnapPointsType="Mandatory"
                  Width="500"
                  Height="500"
                  BorderBrush="Black"
                  BorderThickness="3"
                  RelativePanel.AlignHorizontalCenterWithPanel="True"
                  RelativePanel.AlignVerticalCenterWithPanel="True">


            <StackPanel Grid.Row="1"
                        x:Name="innerPanel"
                        BorderBrush="Yellow"
                        BorderThickness="4"
                    Width="400"
                      Margin="0,90,0,0"  
                    Background="Blue">

                <TextBlock Height="100" Margin="10,0,10,0" Style="{StaticResource SubheaderTextBlockStyle}">Item 1</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0" Style="{StaticResource SubheaderTextBlockStyle}">Item 2</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0" Style="{StaticResource SubheaderTextBlockStyle}">Item 3</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 4</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 5</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 6</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 8</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 9</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 10</TextBlock>
                <TextBlock Height="100" Margin="10,0,10,0"  Style="{StaticResource SubheaderTextBlockStyle}">Item 11</TextBlock>
        </StackPanel>
    </ScrollViewer>
</RelativePanel>

包含的元素需要实现IScrollSnapPointsInfo接口。 StackPanel做到了。

public sealed partial class BlankPage1 : Page
{
    double thresholdValue = 0;
    public BlankPage1()
    {
        this.InitializeComponent();

        outerScroll.ViewChanging += OuterScroll_ViewChanging;

        thresholdValue = innerPanel.Margin.Top + innerPanel.BorderThickness.Top + outerScroll.BorderThickness.Top;

        outerScroll.SizeChanged += (s, e) => { outerScroll.ScrollToVerticalOffset(thresholdValue); };
    }

    private void OuterScroll_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
    {
        if ( e.NextView.VerticalOffset < thresholdValue)
        {
            outerScroll.VerticalSnapPointsType = SnapPointsType.Mandatory;    
        }
        else
            outerScroll.VerticalSnapPointsType = SnapPointsType.None;

        if (e.NextView.VerticalOffset == 0 && !e.IsInertial )
        {
            // Pull to refresh event
            innerPanel.Background = new SolidColorBrush(Colors.Blue);
        }
        else
        {
            // base state
            innerPanel.Background = new SolidColorBrush(Colors.Red);
        }
    }
}

答案 2 :(得分:0)

在GitHub上的微软UWP示例中有一个很好的拉动刷新实现示例。

The link to sample.

其他很棒的样本是listed in Samples folder。请注意,XAML示例名称以“Xaml”开头,因此更容易找到它们。 :)