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();
}
Как только манипуляция будет завершена, вы, конечно же, больше не получите никаких событий.