e.IsInertial почти всегда ложный WPF

У меня есть следующий XAML для моего приложения WPF, которое я конвертирую из 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. Какие-нибудь мысли?

---ОБНОВИТЬ---

С тех пор я обнаружил, что, проводя по большой дуге от верхнего правого к нижнему левому, с полноэкранным экраном, я могу почти вызвать 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)... но мне все еще нужно избавиться от проверки "e.IsInertial". Итак, что-то вызывает использование инерционных дельт до того, как мой обработчик событий их получит

0 ответов

Чтобы убедиться, что поток манипуляций работает так, как задумано, вы хотите обрабатывать больше событий манипуляции и реагировать соответственно. Вот обзор от MS (Обзор ввода - прикосновение и манипуляции), но в целом вы обычно хотите:

  • обработайте ManipulationStarting и установите соответствующий контейнер манипуляции для вашей манипуляции.
  • handle ManipulationStarted, если вы хотите сохранить некоторые данные, такие как источник манипуляции, для ваших собственных вычислений.
  • обрабатывать Дельту, пока пользователь держит палец (-и) вниз
  • handle InertiaStarting - здесь вы должны установить значения замедления.
  • обрабатывать Delta, пока пользователь поднял пальцы (инерционный) - по моему опыту, вы получите эти события, только если вы укажете инерционные значения.
  • handle ManipulationCompleted, если вам нужно знать, когда и где завершился процесс ввода.

Из вашего сообщения я не уверен, знаете ли вы об этом или нет, но InertiaStarting произойдет только после того, как пользователь поднимет палец (и). А затем - если вы установите значения при правильной обработке InertiaStarting - вы получите еще несколько входящих ManipulationDeltas (с флагом Inertial).

После этого у меня больше не работает дельт. Итак, что их потребляет; и почему я сначала получаю неинерционные?

Вы завершили процесс манипуляции, вызвав complete, поскольку проверка if ниже выполнена! Таким образом, "движок" пропустил все остальные события, которые он мог бы запустить, и завершил процесс манипуляции:

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

Как только манипуляция будет завершена, вы, конечно же, больше не получите никаких событий.

Другие вопросы по тегам