在 UWP 应用程序上滚动时禁用枢轴滑动

Disable pivot swipe during scrolling on UWP app

我正在 Windows 10 平台上开发通用 Window 应用程序,我的页面如下例所示:

主页包含一个带有 4 个数据透视表项(第 1 页、第 2 页...)的数据透视表控件。 第 1 页包含一个红色堆栈面板,其中包含一个水平滚动的列表视图。

我的问题是,当我想水平滚动我的红色列表视图时,我的轴滑动到下一页。 我想在列表视图滚动期间禁用枢轴滑动(但仅在列表视图滚动期间)。

我尝试从 listview 获取 scrollviewer 并从 scrollviewer 监听 viewChange 以禁用 pivot 滑动但没有成功。 一切正常,但将 IsHitTestVisible 设置为 false 似乎不起作用。 这是我的代码:

ScrollViewer scrollViewer = ListViewHelper.GetScrollViewer(myListView);
scrollViewer.ViewChanged += scrollview_ViewChanged;

private void scrollview_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
    {
        var scrollviewer = sender as ScrollViewer;

        if (e.IsIntermediate)
        {
            mainPivot.IsHitTestVisible = false;
        } else
        {
            mainPivot.IsHitTestVisible = true;
        }
    }

还有我的 ListViewHelper class :

public static class ListViewHelper
{
    public static ScrollViewer GetScrollViewer(this DependencyObject element)
    {
        if (element is ScrollViewer)
        {
            return (ScrollViewer)element;
        }

        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
        {
            var child = VisualTreeHelper.GetChild(element, i);

            var result = GetScrollViewer(child);
            if (result == null)
            {
                continue;
            }
            else
            {
                return result;
            }
        }

        return null;
    }
}

还有我的 xaml 代码:

<Pivot  x:Name="mainPivot">

        <PivotItem x:Name="pivot1">

            <!-- Header -->
            <PivotItem.Header>
                <controls:TabHeader x:Uid="pivot1HeaderTitle"
                                    Label=""
                                    Glyph="&#xea34;"/>
            </PivotItem.Header>

            <!-- Content -->
            <Grid>

                <Grid.RowDefinitions>
                    <RowDefinition Height="110" />
                    <RowDefinition Height="30" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <StackPanel     x:Name="localeEditionsFavory"
                                Grid.Row="0">

                    [...]

                    <!-- HERE is my listview -->
                    <ListView   x:Name="localeEditionsFavoryList"
                                Height="80"
                                ItemsSource="{Binding FavoritesItems}"
                               ScrollViewer.HorizontalScrollBarVisibility="Auto"
                                ScrollViewer.HorizontalScrollMode="Enabled">

                        <ListView.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Horizontal">
                                </StackPanel>
                            </ItemsPanelTemplate>
                        </ListView.ItemsPanel>

                        <ListView.ItemContainerStyle>
                            <Style TargetType="ListViewItem">
                                <Setter Property="Padding" Value="0,0,0,0" />
                                <Setter Property="Margin" Value="10" />
                                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                            </Style>
                        </ListView.ItemContainerStyle>

                        <ListView.ItemTemplate>
                            <DataTemplate>

                                <Grid   x:Name="favoryList">

                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="90" />
                                    </Grid.ColumnDefinitions>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="55" />
                                    </Grid.RowDefinitions>

                                    <Rectangle  x:Name="strokedasharray" 
                                                Grid.Column="0"
                                                Grid.Row="0"
                                                Fill="White"
                                                Opacity="0.2"
                                                RadiusX="5"
                                                RadiusY="5"/>

                                    <TextBlock  Grid.Column="0"
                                                Grid.Row="0"
                                                Text="{Binding FavoriteItem.EditionKey}" 
                                                TextWrapping="WrapWholeWords" 
                                                Height="auto"
                                                Foreground="White"
                                                FontSize="14"
                                                Margin="2" 
                                                HorizontalAlignment="Center"
                                                VerticalAlignment="Center" 
                                                TextTrimming="CharacterEllipsis" 
                                                TextAlignment="Center"/>

                                </Grid>

                            </DataTemplate>
                        </ListView.ItemTemplate>

                    </ListView>

                </StackPanel>

                [...]

                <ScrollViewer VerticalScrollMode="Auto" 
                              VerticalScrollBarVisibility="Auto"
                              Grid.Row="3">

                    <controls:NewsItemControl   x:Name="NewsListControl"
                                                Visibility="{Binding Busy, Converter={StaticResource InverseBoolToVisibilityConverter}}"/>

                </ScrollViewer>

            </Grid>

        </PivotItem>

        [...]

有没有人有解决这个问题的想法?

如果您需要 ListView 水平滚动,您可以在 XAML 代码中通过修改 ListView 的样式来实现:

<Style x:Key="ListViewStyle" TargetType="ListView">
    <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Hidden" />
    <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Disabled" />
    <Setter Property="ScrollViewer.HorizontalScrollMode" Value="Enabled" />
    <Setter Property="ScrollViewer.IsHorizontalRailEnabled" Value="True" />
    <Setter Property="ScrollViewer.VerticalScrollMode" Value="Disabled" />
    <Setter Property="ScrollViewer.IsVerticalRailEnabled" Value="False" />
    <Setter Property="ItemsPanel">
        <Setter.Value>
            <ItemsPanelTemplate>
                <ItemsStackPanel Orientation="Horizontal" />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>

现在,如果您在滚动 "PAGE 1" 的 ListView 时禁用 Pivot 的滚动,您可以像这样编辑代码:

public void Page_Loaded(object sender, RoutedEventArgs e)
{
    var scrollViewer = FindChildOfType<ScrollViewer>(mainPivot);
    scrollViewer.HorizontalScrollMode = ScrollMode.Disabled;
}

private void PivotSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (mainPivot.SelectedIndex == 0)
    {
        var scrollViewer = FindChildOfType<ScrollViewer>(mainPivot);
        scrollViewer.HorizontalScrollMode = ScrollMode.Disabled;
    }
}

public static T FindChildOfType<T>(DependencyObject root) where T : class
{
    var queue = new Queue<DependencyObject>();
    queue.Enqueue(root);
    while (queue.Count > 0)
    {
        DependencyObject current = queue.Dequeue();
        for (int i = 0; i < VisualTreeHelper.GetChildrenCount(current); i++)
        {
            var child = VisualTreeHelper.GetChild(current, i);
            var typedChild = child as T;
            if (typedChild != null)
            {
                return typedChild;
            }
            queue.Enqueue(child);
        }
    }
    return null;
}

您看到的不良行为是滚动链接的结果。 ListView 和 Pivot 在它们的控件模板中都包含 ScrollViewers,这使得这是一个嵌套的 ScrollViewer 情况。当您有一个包含在另一个树中的 ScrollViewer 并尝试通过触摸滚动超出内部 ScrollViewer 的范围时,外部 ScrollViewer 会参与并开始滚动。

禁用链接后,您只能通过在外部 ScrollViewer 的可命中测试区域开始操作来滚动外部 ScrollViewer。默认情况下,ScrollViewer 启用链接,因此当您尝试滚动到列表末尾时,链接将启动并被 Pivot 识别为尝试“滚动”到下一个 pivot 项目。

通过设置 ScrollViewer.IsHorizontalScrollChainingEnabled="False" 附加 属性:

禁用 ListView 的 ScrollViewer 上的链接(并删除代码后面的 ListViewHelper 内容)
                <!-- HERE is my listview -->
                <ListView   x:Name="localeEditionsFavoryList"
                            Height="80"
                            ItemsSource="{Binding FavoritesItems}"
                            ScrollViewer.IsHorizontalScrollChainingEnabled="False"
                            ScrollViewer.HorizontalScrollBarVisibility="Auto"
                            ScrollViewer.HorizontalScrollMode="Enabled">