C# 在移动设备上忽略在网格上滑动
当用户从组合框中选择条目时,我以编程方式填充ListView 我想通过允许用户左/右滑动来改进应用程序的可用性,作为更改内容的替代方式 更确切地说,当用户执行轻扫或短扫时,listview将填充一组不同的项目。我不需要任何操作已开始的视觉提示(例如,使用手势来回导航时Edge所做的操作) 下面是简化的XAML结构C# 在移动设备上忽略在网格上滑动,c#,uwp,swipe,gesture,windows-10-mobile,C#,Uwp,Swipe,Gesture,Windows 10 Mobile,当用户从组合框中选择条目时,我以编程方式填充ListView 我想通过允许用户左/右滑动来改进应用程序的可用性,作为更改内容的替代方式 更确切地说,当用户执行轻扫或短扫时,listview将填充一组不同的项目。我不需要任何操作已开始的视觉提示(例如,使用手势来回导航时Edge所做的操作) 下面是简化的XAML结构 <Grid x:Name="MainGrid" ManipulationMode="TranslateX, TranslateInertia" Loaded=
<Grid
x:Name="MainGrid"
ManipulationMode="TranslateX, TranslateInertia"
Loaded="MainGrid_Loaded">
<ComboBox x:Name="CBMonthPicker" />
<ListView
x:Name="LV"
ItemsSource="{Binding CalItems, ElementName=page}"
DataContext="MainPage"
IsItemClickEnabled="True"
ItemClick="OnItemClick"
ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">
</ListView>
</Grid>
下面是我用来检测滑动的代码,它在桌面上工作(如果我用鼠标模拟滑动),但在移动设备上不工作(Grid_OperationDelta在移动设备上不触发):
private void主网格\u已加载(对象发送方,路由目标)
{
MainGrid.ManipulationDelta+=网格_ManipulationDelta;
}
专用空心栅格_操纵增量(对象发送器,操纵增量路由导出器)
{
var swiped=e.累计换算.X;
var SwipetriggerThreshold=300;
//如果手势不超过设定的阈值,我们将忽略它
如果(!e.IsInertial | | swiped*swiped
我猜ListView或ListViewItem以某种方式隐藏了对网格的操作
我已经尝试使用ListView和ListViewItem来处理操作,但是它们中的任何一个都不会触发操纵增量,即使我将操纵模式设置为TranslateX、TranslateInertia
关于滑动ListViewItem(如Outlook中的功能),有很多问题。这个问题与那个无关
因为内容是基于用户输入动态加载的,所以我不想使用Pivot。即使我可以,这也意味着对我的界面进行重大更改,我还是不愿意这样做 您的猜测是对的-ListView有一个ScrollViewer,它的工作级别非常低,这提高了性能,但是它首先处理操作,因此“吞咽”了它们。好像不久前我问过
有一种方法可以手动处理这个案例——对它进行了一点描述,它已经很旧了,但应该会给您带来一些启示。您还可以看一下,其中描述了Windows运行时,它也应该在UWP上工作
还请注意,做您想做的事情可能会更容易-如果您将ListView置于Pivot或使用水平ScrollViewer的其他位置,您可以将ListView的ScrollViewer属性更改为true,这会将水平滚动传递给父级。下面是一个XAML代码示例:
第一项
项目
项目
项目
最后一项
在对Pivot进行了大量的修改后,结果完全不令人满意,我发现FlipView可以与一些黑客一起使用,以实现我想要的目标
诀窍是添加两个虚拟FlipViewItems,一个在包含ListView的项目之前,一个在它之后。下一步是捕获FlipView的SelectionChanged事件,如果选择了内容之前的FlipViewItem,则触发一个操作,就像反向滑动一样,内容之后的FlipViewItem也是如此。
最后一步是强制将选择返回到我们的内容ListViewItem
以这种方式对FlipView进行黑客攻击的一个小麻烦是,当强制将选择返回到中间的FlipViewItem(承载内容的FlipViewItem)时,动画与最终用户期望的动画相反。通过在FlipView上设置属性UseTouchAnimationsForAllNavigation=“False”,可以轻松解决此问题
好处:为了显示在重新填充ListView时确实发生了一些事情,我添加了一个进度环。要使其正常工作,FlipView、FlipViewItems和ListView的“背景”属性必须设置为“透明”。ListViewItems有一个指定的背景来覆盖它。对于实现Progressing来说,这是一个完全不雅观的解决方案,但是它可以工作,而且很快就想出了:)
更新后的XAML代码如下所示:
<Grid x:Name="MainGrid" >
<ComboBox x:Name="CBMonthPicker" Grid.Row="0"/>
<ProgressRing Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" IsActive="True" />
<FlipView x:Name="MainView" Grid.Row="1"
Loaded="MainView_Loaded"
UseTouchAnimationsForAllNavigation="False"
Background="Transparent">
<FlipViewItem Background="Transparent">
</FlipViewItem>
<FlipViewItem Background="Transparent">
<ListView x:Name="LV"
ItemsSource="{Binding CalItems, ElementName=page}" DataContext="MainPage"
IsItemClickEnabled="True" ItemClick="OnItemClick"
ItemTemplateSelector="{StaticResource MyDataTemplateSelector}">
</ListView>
</FlipViewItem>
<FlipViewItem Background="Transparent">
</FlipViewItem>
</Grid>
private void MainView_Loaded(object sender, RoutedEventArgs e)
{
MainView.SelectedIndex = 1;
MainView.SelectionChanged += MainView_SelectionChanged;
}
private void MainView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (MainView.SelectedIndex == 0)
{
//perform the action for Back Swipe Gesture
changeDisplayedMonth(-1);
//force selection back to our content FlipViewItem
MainView.SelectedIndex = 1;
}
if (MainView.SelectedIndex == 2)
{
//perform the action for Forward Swipe Gesture
changeDisplayedMonth(1);
//force selection back to our content FlipViewItem
MainView.SelectedIndex = 1;
}
}
只是为了了解您的UI:您有一个覆盖在组合框上的ListView,用户可以与两者交互?或者它们在彼此下面?combobox和listview共享同一个网格(在我的XAML示例中是MainGrid),但它们放在不同的行上。它们不重叠。值得注意的是,如果我在组合框上滑动,滑动可以在移动设备上工作。如果我理解正确,您的方法是为listview手动实现垂直滚动,同时捕获和处理滑动手势。我还从您对另一个问题的回答中了解到,在此操作过程中,滚动平滑度丢失。如果是这样的话,我宁愿不要那条路线。另外,您关于用水平滚动容器包装listview的其他建议也不起作用。不仅是操纵增量事件从未触发(在任何容器和listview本身上),而且在执行此操作时布局严重损坏。@brett我不确定您最后想要实现什么。如果您像xaml示例中那样链接滚动条,那么您不需要ManiplationDelta,您在fresh应用程序上尝试过这段代码吗?此外,如果你需要更多的滚动逻辑,你可以随时订阅水平滚动查看器的事件。我已经更新了问题,以澄清我想要的结果
private void MainView_Loaded(object sender, RoutedEventArgs e)
{
MainView.SelectedIndex = 1;
MainView.SelectionChanged += MainView_SelectionChanged;
}
private void MainView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (MainView.SelectedIndex == 0)
{
//perform the action for Back Swipe Gesture
changeDisplayedMonth(-1);
//force selection back to our content FlipViewItem
MainView.SelectedIndex = 1;
}
if (MainView.SelectedIndex == 2)
{
//perform the action for Forward Swipe Gesture
changeDisplayedMonth(1);
//force selection back to our content FlipViewItem
MainView.SelectedIndex = 1;
}
}