e.IsInertial几乎总是假的WPF

时间:2018-04-22 18:45:22

标签: wpf swipe inertia .net-4.7 inertial-navigation

我的WPF应用程序有以下XAML,我将从UWP转换:

<ScrollViewer Name="scv_main" Grid.Row="2" ScrollViewer.VerticalScrollBarVisibility="Auto" 
PanningMode="VerticalFirst">
    <TextBlock Name="txbl_display" Grid.Row="2"  Foreground="White"
     FontFamily="Lucida Console" FontSize="22" Text="{Binding Path=ContentPath, Mode=OneWay, 
     UpdateSourceTrigger=PropertyChanged}" Padding="20" TextWrapping="Wrap" 
     IsManipulationEnabled="True" ManipulationDelta="manipulationDeltaHandler"/>
</ScrollViewer>

我发现的是,事件处理程序e.IsInertial始终为假。

我认为可能是ScrollViewer处理惯性事件,但是当我删除ScrollViewer时,我仍然无法获得任何惯性事件。我也尝试将ManipulationDelta放在ScrollViewer上,结果相同。

我的最终目标是我希望ScrollViewer在非惯性移动时滚动,但让我控制惯性滑动时发生的事情。

我在UWP应用程序中管理了这个效果,我将其移植到WPF,如下所示:

<TextBlock ... ManipulationMode="All" ManipulationDelta="TextBlock_ManipulationDelta/>"

然后在代码隐藏中:

if (e.IsInertial) // inertial = swipe, rather than slide
{
    // X-Translation - change contents of textblock
    if (e.Cumulative.Translation.X <= -500) //500 is the threshold value, where you want to trigger the swipe right event
    {
        showNext();
        e.Complete();
    }
    else if (e.Cumulative.Translation.X >= 500)
    {
        showPrevious();
        e.Complete();
    }

    // Y translation - move the scrollbar
    else if (e.Cumulative.Translation.Y <= -500)
    {
        scv_main.ChangeView(null, scv_main.VerticalOffset + (-1 * e.Cumulative.Translation.Y), null);
        e.Complete();
    }
    else if (e.Cumulative.Translation.Y >= 500)
    {
        scv_main.ChangeView(null, Math.Min(scv_main.VerticalOffset + (-1 * e.Cumulative.Translation.Y), 0), null);
        e.Complete();
    }
}
else // slide,rather than swipe - scroll as the finger moves
{
    if (e.Delta.Translation.Y != 0)
    {
        scv_main.ChangeView(null, scv_main.VerticalOffset + (-1 * e.Delta.Translation.Y), null);
    }
}

但我无法在WPF中重复此行为。有什么想法吗?

--- --- UPDATE

我已经发现,通过从右上角到左下角的大弧度滑动,屏幕全屏,我可以触发e.IsInertial = True事件。发生这种情况时,ManipulationDelta事件会被触发两次 - 第一次使用e.IsInertial = false,第二次使用e.IsInertial = true。我不确定为什么会这样;无论如何,这不是我正在寻找的行为。

有人有更多想法吗?我尝试了各种各样的事情,包括在所有事情上放置一个面板并将操纵处理器放在上面;但我仍然遇到同样的问题。

我正在使用Visual Studio 2017和Windows 10.我正在编码和测试的设备是Microsoft Surface Book

似乎正在发生的事情是,非惯性行动首先发生;然后,一旦完成,惯性就会发射。我在事件中放了一些输出,当我刷过时得到了以下内容:

ManipulationStarting Fired ManipulationDelta e.IsInertial = False. X,Y:-5.14288330078125,-1.14288330078125 ManipulationDelta e.IsInertial = False. X,Y:-16.5714111328125,0 ManipulationDelta e.IsInertial = False. X,Y:-16.5714111328125,0 ManipulationDelta e.IsInertial = False. X,Y:-89.1428833007813,1.14288330078125 ManipulationDelta e.IsInertial = False. X,Y:-224,2.28570556640625 ManipulationDelta e.IsInertial = False. X,Y:-224,2.28570556640625 ManipulationDelta e.IsInertial = False. X,Y:-384.571441650391,4 ManipulationDelta e.IsInertial = False. X,Y:-622.285705566406,4 ManipulationDelta e.IsInertial = False. X,Y:-622.285705566406,4 ManipulationDelta e.IsInertial = False. X,Y:-622.285705566406,4 ManipulationDelta e.IsInertial = False. X,Y:-732.571411132813,6.28570556640625 ManipulationDelta e.IsInertial = False. X,Y:-732.571411132813,6.28570556640625 ManipulationDelta e.IsInertial = False. X,Y:-732.571411132813,6.28570556640625 ManipulationDelta e.IsInertial = False. X,Y:-732.571411132813,6.28570556640625 ManipulationInertiaStarting Fired

在那之后,我再也没有获得任何增量。那么消费它们的是什么;为什么我先得到非惯性的?

我发现实现这种工作的一种方法是将PanningMode="VerticalFirst"更改为PanningMode="None"。然后自己处理滚动(这似乎是UWP版本正在做的事情)......但我仍然要摆脱&#34; e.IsInertial&#34;校验。因此,在我的事件处理程序获取惯性增量之前,某些东西会导致惯性增量消耗

1 个答案:

答案 0 :(得分:1)

为确保操纵流按预期工作,您想处理更多操纵事件并做出相应反应。这是MS(Input overview - Touch and manipulations)的概述,但总的来说,您通常希望:

  • 处理操纵开始并为您的操纵设置适当的操纵容器。
  • 处理操作开始,如果您想存储一些数据,例如用于您自己的计算的处理源。
  • 在用户不放手指的情况下处理Delta
  • 处理InertiaStarting-在此处应设置减速度值。
  • 在用户抬起手指(惯性)时处理Delta-根据我的经验,只有指定惯性值,您才会得到这些事件。
  • 处理操作完成,如果您需要知道输入过程的完成时间和地点。

从您的帖子中我不确定您是否知道这一点,但是InertiaStarting仅在用户松开手指后才会发生。然后-如果您在正确处理InertiaStarting时设置值-您将获得更多的ManipulationDeltas输入(带有Inertial标志)。

  

在那之后,我再也没有发射三角洲了。那么什么在消耗它们呢?为什么我要先获得非惯性武器?

您已通过调用complete来完成操纵过程,因为已完成以下if检查!因此,“引擎”已跳过了所有其他可能触发的事件,并完成了操作过程:

if (e.Cumulative.Translation.X <= -500)
{
    showNext();
    e.Complete();
}

一旦操作完成,您当然不会再有任何事件了。