当用户从ComboBox中选择一个条目时,我以编程方式填充ListView。
我想通过允许用户向左/向右滑动作为更改内容的替代方式来改善应用可用性。
更准确地说,当用户执行轻弹或短滑动时,列表视图会填充不同的项目集。我不需要任何操作已经开始的视觉提示(即使用手势来回导航时像Edge一样)
以下是简化的XAML结构。
<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_ManipulationDelta不会在移动设备上触发):
private void MainGrid_Loaded(object sender, RoutedEventArgs e)
{
MainGrid.ManipulationDelta += Grid_ManipulationDelta;
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var swiped = e.Cumulative.Translation.X;
var swipeTriggerThreshhold = 300;
//if the gesture was not above a set threshold we ignore it
if (!e.IsInertial || swiped * swiped < swipeTriggerThreshhold * swipeTriggerThreshhold )
return;
//If we got so far, we registered a swipe
e.Complete(); //end manipulation so we only handle it once
if (swiped < 0) { //we swiped left
changeDisplayedMonth(-1);
}
else{ //we swiped right
changeDisplayedMonth(1);
}
}
我的猜测是ListView或ListViewItem以某种方式隐藏了Grid中的操作。
我尝试使用ListView和ListViewItem来处理操作,但是ManipulationDelta永远不会被触发,即使我将ManipulationMode设置为TranslateX,TranslateInertia。
对于ListViewItem的滑动(如Outlook中的特色),有很多关于SO的问题。这个问题与此无关。
因为内容是根据用户输入动态加载的,所以我宁愿不使用Pivot。即使我可以,这也意味着我的界面会发生重大变化,而我也不愿意这样做。
答案 0 :(得分:0)
你的猜测是正确的 - ListView 有一个 ScrollViewer ,它的工作水平非常低,可以提高性能,但是它首先要处理操作,因此它&#39;燕子&#39;他们。似乎前段时间我似乎已经问a similar question。
有一种方法可以手动处理这种情况 - Rob Caplan's blog post描述了一点,它已经很老了,但应该给你带来一些启发。您还可以查看<{>> Windows-Runtime 所描述的at this answer,它在 UWP 上的工作方式也类似。
另请注意,如果您将 ListView 放在 Pivot 中或使用水平 ScrollViewer 的内容,可能更容易做到你想要的,您可以将 ListView&#39> ScrollViewer 的属性IsHorizontalScrollChainingEnabled更改为true,这会将水平滚动传递给父级。这是一个示例XAML代码:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<ScrollViewer HorizontalScrollMode="Enabled" HorizontalScrollBarVisibility="Visible">
<StackPanel Orientation="Horizontal">
<ListView Width="200" Height="100" ScrollViewer.IsHorizontalScrollChainingEnabled="True">
<x:String>First Item</x:String>
<x:String>Item</x:String>
<x:String>Item</x:String>
<x:String>Item</x:String>
<x:String>Last Item</x:String>
</ListView>
<Rectangle Width="200" Height="100" Fill="Red"/>
<Rectangle Width="200" Height="100" Fill="Green"/>
<Rectangle Width="200" Height="100" Fill="Blue"/>
</StackPanel>
</ScrollViewer>
</Grid>
答案 1 :(得分:0)
经过大量摆弄Pivot后产生了令人不满意的结果,我发现FlipView可以用一些黑客来完成我想要的。
诀窍是添加两个虚拟FlipViewItem,一个在包含ListView的一个之前,一个在它之后。下一步是捕获FlipView的SelectionChanged事件,如果选择了我们内容之前的FlipViewItem,则触发一个动作,就像对后一次滑动一样,对于我们内容之后的FlipViewItem也是如此。 最后一步是强制选择回到我们的内容ListViewItem。
以这种方式入侵的FlipView的一个小烦恼是,当强制选择回到我们的中间FlipViewItem(托管我们的内容的那个)时,动画与最终用户期望的动画相反。通过在FlipView上设置属性UseTouchAnimationsForAllNavigation =“False”可以轻松解决此问题。
奖励:为了表明在重新填充ListView时实际发生了某些事情,我添加了一个进度环。为此,重要的是FlipView和FlipViewItems以及ListView将其Background属性设置为Transparent。 ListViewItems具有指定的背景来覆盖它。这对于实现ProgressRing来说是一个非常不优雅的解决方案,但是它很有效,并且提出来很快:)。
这就是更新的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;
}
}