e.IsInertial几乎总是假的WPF

sim*_*005 9 wpf swipe inertial-navigation .net-4.7

我为我的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>
Run Code Online (Sandbox Code Playgroud)

我发现的是,事件处理程序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);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是我不能在WPF中重复这种行为.有什么想法吗?

--- UPDATE ---

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

有没有人有更多的想法?我尝试过各种各样的事情,包括将一个面板放在所有东西的顶部并将操纵处理器放在上面; 但我仍然遇到同样的问题.

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


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

PanningMode="VerticalFirst"

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

我发现获得这种工作的一种方法是PanningMode="None"改为e.IsInertial.然后自己处理滚动(这似乎是UWP版本正在做的事情)......但我还是要摆脱"e.IsInertial"检查.因此,在我的事件处理程序获取惯性增量之前,会导致惯性增量消耗

小智 1

为了确保操作流程按预期工作,您需要处理更多的操作事件并做出相应的反应。以下是 MS 的概述(输入概述 - 触摸和操作),但一般来说,您通常想要:

  • 处理 ManipulationStarting 并为您的操作设置正确的操作容器。
  • 如果您想存储一些数据(例如操作的起源)以供您自己的计算,请处理 ManipulationStarted。
  • 当用户手指向下时处理 Delta
  • 处理 InertiaStarting - 在这里您应该设置减速度值。
  • 当用户抬起手指时处理 Delta(惯性) - 根据我的经验,只有指定惯性值时,您才会收到这些事件。
  • 如果您需要知道输入过程何时何地完成,请处理 ManipulationCompleted。

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

在那之后,我再也没有听到任何三角洲射击。那么是什么在消耗他们?为什么我首先得到非惯性的?

您已经通过调用完成完成了操作过程,因为下面的 if 检查已经完成!因此,“引擎”已经跳过了它本来会触发的所有其余事件并完成了操作过程:

if (e.Cumulative.Translation.X <= -500)
{
    showNext();
    e.Complete();
}
Run Code Online (Sandbox Code Playgroud)

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