Often when creating an application you will want a secondary mechanism for executing a command, the primary mechanism will often be a button click (e.g. Opening a record). In MVVM the backing ViewModel will expose an ICommand which is bound to the Button’s Command. This behavior executes the same command when a double click occurs.
Sample Application:
How:
- Register to the Mouse Up event on the AssociatedObject, we use the Mouse Up event so that we can attach the behavior to DataGrid / ListBox templates as the Mouse Down events are swallowed by these.
- Create a dependancy property for the ICommand and the ClickInterval (this will commonly be hard coded by exists for demonstration purposes)
- Set up a DispatcherTimer with the desired interval, also attach the Tick event and stop the timer.
- When Mouse Up occurs event occurs the first time we start the DispatcherTimer.
- For a double click to occur the Mouse Up event must be raised while the timer is active, if it is then we execute the Command and stop the timer.
Code:
public class DoubleClickBehavior : Behavior<UIElement>
{
private readonly DispatcherTimer _timer = new DispatcherTimer();
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseLeftButtonUp += AssociatedObjectMouseLeftButtonUp;
_timer.Tick += new EventHandler(_timerTick);
_timer.Interval = TimeSpan.FromSeconds(ClickInterval);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseLeftButtonUp -= AssociatedObjectMouseLeftButtonUp;
}
private void _timerTick(object sender, EventArgs e)
{
_timer.Stop();
}
private void AssociatedObjectMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (!_timer.IsEnabled)
{
// If the timer is not already running then start it.
_timer.Start();
}
else
{
_timer.Stop();
if(CommandToExecute != null)
{
// If the timer is active there has been a second event so execute the command.
CommandToExecute.Execute(this);
}
}
}
public static readonly DependencyProperty IntervalProperty =
DependencyProperty.Register("ClickInterval",
typeof(double),
typeof(DoubleClickBehavior),
new PropertyMetadata(0.25,
new PropertyChangedCallback(OnClickIntervalChanged)));
private static void OnClickIntervalChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var doubleClick = (DoubleClickBehavior)sender;
doubleClick._timer.Interval = TimeSpan.FromSeconds(doubleClick.ClickInterval);
}
public double ClickInterval
{
get { return (double)GetValue(IntervalProperty); }
set { SetValue(IntervalProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("CommandToExecute",
typeof(ICommand),
typeof(DoubleClickBehavior),
new PropertyMetadata(null));
public ICommand CommandToExecute
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
}
public class DoubleClickBehavior : Behavior<UIElement>
{
private readonly DispatcherTimer _timer = new DispatcherTimer();
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.MouseLeftButtonUp += AssociatedObjectMouseLeftButtonUp;
_timer.Tick += new EventHandler(_timerTick);
_timer.Interval = TimeSpan.FromSeconds(ClickInterval);
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.MouseLeftButtonUp -= AssociatedObjectMouseLeftButtonUp;
}
private void _timerTick(object sender, EventArgs e)
{
_timer.Stop();
}
private void AssociatedObjectMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (!_timer.IsEnabled)
{
// If the timer is not already running then start it.
_timer.Start();
}
else
{
if(CommandToExecute != null)
{
// If the timer is active there has been a second event so execute the command.
CommandToExecute.Execute(this);
}
}
}
public static readonly DependencyProperty IntervalProperty =
DependencyProperty.Register(“ClickInterval”,
typeof(double),
typeof(DoubleClickBehavior),
new PropertyMetadata(0.25,
new PropertyChangedCallback(OnClickIntervalChanged)));
private static void OnClickIntervalChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
{
var doubleClick = (DoubleClickBehavior)sender;
doubleClick._timer.Interval = TimeSpan.FromSeconds(doubleClick.ClickInterval);
}
public double ClickInterval
{
get { return (double)GetValue(IntervalProperty); }
set { SetValue(IntervalProperty, value); }
}
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register(“CommandToExecute”,
typeof(ICommand),
typeof(DoubleClickBehavior),
new PropertyMetadata(null));
public ICommand CommandToExecute
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
}