Событие, когда кнопка удерживается нажатой в течение некоторого времени
Я моделирую портативное устройство с WPF и MVVM (viewmodel - это конечный автомат, view - это имитируемый пластиковый корпус с кнопками).
Жест, который включает и выключает устройство - это "длинный щелчок" в кнопке. Например, во время использования, если я нажимаю кнопку "ОК", он отображает некоторый экран, но если я УДЕРЖИВАЮ на нем нажатие более трех секунд, он должен (имитировать) выключить устройство.
Я заглянул в RepeatButton
, с этими Delay
а также Interval
свойства, но те, кажется, стреляют одинаково Click
событие. Что мне нужно, это уволить регулярно Click
если я удерживаю кнопку менее трех секунд и запускаю другую, другую LongClick
(возможно, один раз), если я буду держать его более трех секунд.
Как я могу сделать это, используя RepeatButton или даже обычную кнопку?
2 ответа
Один из способов сделать это - привязать события MouseDown и MouseUp. Используйте что-то вроде секундомера, который запускается на MouseDown, и проверьте, сколько времени прошло на MouseUp. Если это менее 3 секунд, выполните действие Click(). Если это более 3 секунд, выполните действие LongClick().
private void Button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
stopwatch = new Stopwatch();
stopwatch.Start();
}
private void Button_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
stopwatch.Stop();
if (stopwatch.ElapsedMilliseconds >= 3000)
{
// do Click()
}
else
{
// do LongClick
}
}
И вот решение для RepeatButton:
private bool isLongClick;
private bool hasAlreadyLongClicked;
private void RepeatButton_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
isLongClick = false;
hasAlreadyLongClicked = false;
stopwatch = new Stopwatch();
stopwatch.Start();
}
private void RepeatButton_Click(object sender, RoutedEventArgs e)
{
if (!hasAlreadyLongClicked && stopwatch.ElapsedMilliseconds >= 3000)
{
hasAlreadyLongClicked = true;
isLongClick = true;
// do your LongClick action
}
}
private void RepeatButton_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (!isLongClick)
{
// do short click action
}
}
Хитрость в том, что RepeatButton - это, по сути, просто кнопка, которая запускает Click на каждом интервале. Таким образом, если мы запускаем секундомер в PreviewMouseDown для кнопки, мы можем проверять истекшее время на секундомере каждый раз, когда срабатывает событие Click, и изменять наше действие в зависимости от результата.
После медитации на выходных я разработал следующее рабочее решение:
- Создайте два логических флага в ViewModel:
ClickedShort
а такжеClickedLong
; - Связывание
Command
свойство на кнопке, через команду, чтобыOK
метод на ViewModel; Команда ОК выглядит так:
public void OK() { if (!ClickedShort) { HandleShortClick(); ClickedShort = true; } else if (!ClickedLong) { HandleLongClick(); ClickedLong = true; } }
Есть два флажка в XAML, с
IsChecked
свойства, связанные с логическими флагами. Это просто реле, так что я могу отправлять информацию из View в ViewModel через привязку:<CheckBox x:Name="ClickedShort" IsChecked="{Binding ClickedShort, Mode=OneWayToSource}" Visibility="Collapsed"/> <CheckBox x:Name="ClickedLong" IsChecked="{Binding ClickedLong, Mode=OneWayToSource}" Visibility="Collapsed"/>
Есть
MouseUp
событие в кнопке ОК, чтобы сбросить эти флаги на ложь, когда я отпущу кнопку.