[英]MVVM: Button Hold event command
I want to be able to assign two different Command
to a Button
:我希望能够将两个不同的
Command
分配给Button
:
Click
event Command
Click
事件Command
Hold
event Command which uses HoldTimeout
property to specify the hold duration Hold
事件命令,它使用HoldTimeout
属性来指定保持持续时间
public static readonly DependencyProperty HoldCommandProperty = DependencyProperty.Register( "HoldCommand", typeof(ICommand), typeof(CommandButton), new PropertyMetadata(null, CommandChanged)); public ICommand HoldCommand { get { return (ICommand)GetValue(CommandProperty); } set { SetValue(CommandProperty, value); } }
How to calculate the time for click & hold and where should the calculation be done?如何计算点击和保持的时间以及应该在哪里进行计算? I am not sure if handling Click event is the right place if using the 'Command' property of an button.
如果使用按钮的“命令”属性,我不确定处理 Click 事件是否合适。
The result XAML should look something like that:结果 XAML 应如下所示:
<CommandButton x:Name="InputButton"
Command="{Binding PrimaryCommand}"
CommandParameter="{Binding}"
HoldCommand="{Binding SecondaryCommand}"
HoldCommandParameters="{Binding}"
HoldTimeout="2000"/>
I have read how to implement double-clicks but this is not exactly it:我已经阅读了如何实现双击,但这不完全是这样:
You need to create a custom control and use DispatcherTimer class to time it.您需要创建一个自定义控件并使用 DispatcherTimer 类对其进行计时。 You can add another boolean and command property to activate this behaviour.
您可以添加另一个布尔值和命令属性来激活此行为。
the control is as follows:控制如下:
public class SmartButton : Button
{
private DispatcherTimer _timer;
public int MillisecondsToWait
{
get { return (int)GetValue(MillisecondsToWaitProperty); }
set { SetValue(MillisecondsToWaitProperty, value); }
}
public DispatcherTimer Timer
{
get { return _timer; }
set { _timer = value; }
}
public ICommand ClickAndHoldCommand
{
get { return (ICommand)GetValue(ClickAndHoldCommandProperty); }
set { SetValue(ClickAndHoldCommandProperty, value); }
}
public bool EnableClickHold
{
get { return (bool)GetValue(EnableClickHoldProperty); }
set { SetValue(EnableClickHoldProperty, value); }
}
// Using a DependencyProperty as the backing store for EnableClickHold. This enables animation, styling, binding, etc...
public static readonly DependencyProperty EnableClickHoldProperty =
DependencyProperty.Register("EnableClickHold", typeof(bool), typeof(SmartButton), new PropertyMetadata(false));
// Using a DependencyProperty as the backing store for ClickAndHoldCommand. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ClickAndHoldCommandProperty =
DependencyProperty.Register("ClickAndHoldCommand", typeof(ICommand), typeof(SmartButton), new UIPropertyMetadata(null));
// Using a DependencyProperty as the backing store for MillisecondsToWait. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MillisecondsToWaitProperty =
DependencyProperty.Register("MillisecondsToWait", typeof(int), typeof(SmartButton), new PropertyMetadata(0));
public SmartButton()
{
this.PreviewMouseLeftButtonUp += OnPreviewMouseLeftButtonUp;
this.PreviewMouseLeftButtonDown += OnPreviewMouseLeftButtonDown;
}
private void OnPreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (EnableClickHold)
{
bool isMouseReleaseBeforeHoldTimeout = Timer.IsEnabled;
ResetAndRemoveTimer();
// Consider it as a mouse click
if (isMouseReleaseBeforeHoldTimeout && Command != null)
{
Command.Execute(CommandParameter);
}
e.Handled = true;
}
}
private void OnPreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (EnableClickHold)
{
Timer = new DispatcherTimer(DispatcherPriority.Normal, this.Dispatcher)
{
Interval = TimeSpan.FromMilliseconds(MillisecondsToWait)
};
Timer.Tick += Timer_Tick;
Timer.IsEnabled = true;
Timer.Start();
e.Handled = true;
}
}
void Timer_Tick(object sender, EventArgs e)
{
if(ClickAndHoldCommand != null)
{
this.ClickAndHoldCommand.Execute(this.CommandParameter);
}
ResetAndRemoveTimer();
}
private void ResetAndRemoveTimer()
{
if (Timer == null) return;
Timer.Tick -= Timer_Tick;
Timer.IsEnabled = false;
Timer.Stop();
Timer = null;
}
}
The xaml of this should look like这个 xaml 应该看起来像
<wpfMouseClick:SmartButton x:Name="MySmartButton"
Width="100"
Height="50"
ClickAndHoldCommand="{Binding Path=MyTestCommand,
ElementName=MyWindow}"
EnableClickHold="True"
MillisecondsToWait="1000">
Click and Hold
</wpfMouseClick:SmartButton>
Look into the RepeatButton control, which fires a Click
event repeatedly from the time you click it to the time it is released.查看RepeatButton控件,该控件从您单击它到释放它时重复触发
Click
事件。
To expand on this, you can control the interval of Click
events fired, and keep track of how many will execute in a given time.为了扩展这一点,您可以控制触发
Click
事件的间隔,并跟踪在给定时间内将执行多少次。 For example, if the Interval
property is set to 1000 , it will fire a Click
event every second.例如,如果
Interval
属性设置为1000 ,它将每秒触发一个Click
事件。 Keep track of how many are fired with a counter;跟踪有多少被计数器触发; once 5 have fired this means the user held the button down for five seconds and you can put your "Click & Hold" event logic in the
RepeatButton
Click
event handler and then reset the counter.一旦5触发,这意味着用户按住按钮五秒钟,您可以将“单击并按住”事件逻辑放在
RepeatButton
Click
事件处理程序中,然后重置计数器。
How about using EventTriggers and a StopWatch.如何使用 EventTriggers 和 StopWatch。
<UserControl xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="PreviewMouseDown">
<i:InvokeCommandAction Command="{Binding DownCmd}" />
</i:EventTrigger>
<i:EventTrigger EventName="PreviewMouseUp">
<i:InvokeCommandAction Command="{Binding UpCmd}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</UserControl>
This is the C#.这是 C#。 I am using the code in a ViewModel.
我在 ViewModel 中使用代码。
Stopwatch _buttonHoldStopWatch;
public DelegateCommand DownCmd { get; set; }
public DelegateCommand UpCmd { get; set; }
// Delegate commands are from the Prism framework but you can switch these out to
regular ICommands
ResetValueDownCmd = new DelegateCommand(Down);
ResetValueUpCmd = new DelegateCommand(Up);
// User pressed down
private void Down(object dayObject)
{
_buttonHoldStopWatch.Start(); // start watch
}
// User left go of press
private void Up(object dayObject)
{
// Did the user hold down the button for 0.5 sec
if (_buttonHoldStopWatch.ElapsedMilliseconds >= 500)
{
// Do something
}
_buttonHoldStopWatch.Stop(); // stop watch
_buttonHoldStopWatch.Reset(); // reset elapsed time
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.