2017-02-10 54 views
3

我在用户从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的(S)在某种程度上隐藏在电网的操作。

我已经尝试使用ListView和ListViewItem来处理操作,但是ManipulationDelta从来没有被触发任何它们,即使我将ManipulationMode设置为TranslateX,TranslateInertia。

有很多关于滑动ListViewItem(如Outlook中的功能)的问题。这个问题与此无关。

由于内容是根据用户输入动态加载的,我宁愿不使用Pivot。即使我可以,这也意味着我的界面发生了重大变化,我再也不想这么做了。

+0

只是想了解你的用户界面:你有一个ListView覆盖了ComboBox和用户可以与两者进行交互?或者它们低于彼此? – schumi1331

+0

组合框和列表视图共享相同的网格(我的XAML示例中的MainGrid),但放置在单独的行上。它们不重叠。值得注意的是,如果我在组合框上滑动,则可以在移动设备上进行滑动。 – brett

回答

0

很多与绕着摆弄它产生完全令人满意的结果后,我发现FlipView可能带着几分黑客来完成正是我想要的使用。

诀窍是添加两个虚拟FlipViewItems,一个包含我们的ListView之前,一个之后。下一步是捕获FlipView的SelectionChanged事件,并且如果我们的内容之前的FlipViewItem已被选中,则触发一个操作,就像您对后面的滑动操作一样,对于内容之后的FlipViewItem也是如此。 最后一步是强制选择回到我们的内容ListViewItem。

FlipView以这种方式受到的一个小烦恼是,当强制选择回到我们的中间FlipViewItem(托管我们的内容的那个)时,动画与最终用户期望的动画相反。这可以通过在FlipView上设置属性UseTouchAnimationsForAllNavigation =“False”来解决。

奖励:为了显示重新填充ListView时实际发生的事情,我添加了一个进度环。为此,重要的是FlipView和FlipViewItems以及ListView的Background Property设置为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;     
     }    
    } 
0

你的猜测是正确的 - 的ListView的ScrollViewer这是工作在一个非常低的水平,从而提高了性能,但其照顾操纵第一,因此“燕子”他们。似乎前一段时间似乎我问过a similar question

有一种方法来手动处理这种情况 - Rob Caplan's blog post介绍了一点,这是很老,但应该给你带来一些轻。您还可以看看at this answer,在那里它是Windows的运行,这也应该UWP工作类似描述。

还要注意它可能会更容易做你想做的 - 如果你把你的的ListView枢轴或水平的ScrollViewer的东西,你可以更改属性ListView的的ScrollViewerIsHorizontalScrollChainingEnabled来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> 
+0

如果我理解正确,你的方法是实现手动垂直滚动列表视图,同时捕获和处理滑动手势。我从另一个问题的答案中读到的是,在此操作过程中,滚动平滑度丢失。如果情况确实如此,我宁愿没有那样的路线。另外你的其他建议包装水平滚动容器的列表视图不起作用。 ManipulationDelta事件不仅触发(在任何容器和列表视图本身上),但是这样做时布局严重中断。 – brett

+0

@brett我不确定你最终想达到什么目的。如果你像xaml示例中的链接滚动,那么你不需要ManiplationDelta,你有没有试过这个代码在新鲜的应用程序?另外,如果您需要更多的滚动逻辑,您可以始终订阅水平滚动查看器的事件。 – Romasz

+0

我已经更新了这个问题来澄清我期望的结果。我的应用程序中没有水平滚动任何位置。只有垂直。 – brett