在 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=""/>
</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">
我正在 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=""/>
</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"
附加 属性:
<!-- HERE is my listview -->
<ListView x:Name="localeEditionsFavoryList"
Height="80"
ItemsSource="{Binding FavoritesItems}"
ScrollViewer.IsHorizontalScrollChainingEnabled="False"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollMode="Enabled">