在移动设备上忽略网格滑动

时间:2017-02-10 20:43:41

标签: c# uwp swipe gesture windows-10-mobile

当用户从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。即使我可以,这也意味着我的界面会发生重大变化,而我也不愿意这样做。

2 个答案:

答案 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;                
        }            
    }