Reputation: 965
My Requirement: I want to set custom command for my WPF button, inside the custom command execution I want to know whether the command executed by mouse single click or double click. Also when the customCommand's CanExecute returns false, I want the button to go on disable state. please refer below for more details.
Description: Hi, In WPF I have set custom command for my button. When I click the button(For both single click and double click) the command gets executed. Inside the custom command I want to handle a separate action for single click and double click. Is it possible to find whetehr button single clicked or double this inside commands?? I use .Net 4.0, c#4.0
Note : I referred this How to bind a command in WPF to a double click event handler of a control? but I faced a limitation here.
Limitation:
When I set the custom command for my button then on CustomCommand CanExcute returns false the button goes to disable state. but As per the above Suggestion, by setting the command to mouse binding and setting the mouse binding to button works but when CanExecute returns false, the button doesnt goes to disable state. How to overcome this
public CustomCommand: ICommandd { public bool CanExecute(object parameter) { //arbitrary logic }
public void Execute(object parameter)
{
if(MouseSingleClick)
{
perform ActionA;
}
if(MouseDoubleClick)
{
PerformActionB;
}
}
}
Thanks in Advance.
Upvotes: 0
Views: 1115
Reputation: 3004
I was able to use this and tweak it to use it in MVVM friendly way.
I am giving a working example using Cinch framework.
I hoe this helps you give the idea to get going.
MyViewModel
public class MyViewModel : INotifyPropertyChanged
{
private static DispatcherTimer myClickWaitTimer =
new DispatcherTimer (
new TimeSpan (0, 0, 0, 0, 150),
DispatcherPriority.Background,
mouseWaitTimer_Tick,
Dispatcher.CurrentDispatcher);
private static void mouseWaitTimer_Tick (object sender, EventArgs e)
{
myClickWaitTimer.Stop ();
Debug.WriteLine ("Single Click Executed");//PerformActionA
}
public ICommand CinchSingleClickCommand { get; private set; }
public ICommand CinchDoubleClickCommand { get; private set; }
public MyViewModel ()
{
CinchSingleClickCommand = new SimpleCommand<object, EventToCommandArgs> (CanExecuteSingleCinch, ExecuteSingleCinch);
CinchDoubleClickCommand = new SimpleCommand<object, EventToCommandArgs> (CanExecuteDoubleCinch, ExecuteDoubleCinch);
myClickWaitTimer.Stop ();
}
private void ExecuteDoubleCinch (EventToCommandArgs obj)
{
if (obj.EventArgs is MouseEventArgs)
{
myClickWaitTimer.Stop ();
Debug.WriteLine ("Double Click Executed");//PerformActionB
var mouseEvent = obj.EventArgs as MouseEventArgs;
mouseEvent.Handled = true;
}
}
private bool CanExecuteDoubleCinch (object arg)
{
return true;
}
private void ExecuteSingleCinch (EventToCommandArgs obj)
{
if (!(obj.EventArgs is MouseEventArgs))
{
myClickWaitTimer.Start ();
var mouseEvent = obj.EventArgs as RoutedEventArgs;
mouseEvent.Handled = true;
}
}
private bool CanExecuteSingleCinch (object arg)
{
return true;
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged (string propertyName)
{
var pc = PropertyChanged;
if (pc != null)
pc (this, new PropertyChangedEventArgs (propertyName));
}
}
You can play with the TimeSpan constructor to set how much delay do you want to keep between the single click and the double click.
The View
<Window x:Class="DataGridTesting.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:cinch="clr-namespace:Cinch;assembly=Cinch.WPF"
Title="MainWindow"
Height="350"
Width="525">
<DockPanel>
<Button x:Name="button"
Content="Test">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<cinch:EventToCommandTrigger Command="{Binding CinchDoubleClickCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="Click">
<cinch:EventToCommandTrigger Command="{Binding CinchSingleClickCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DockPanel>
</Window>
The Code behind for the view
public partial class MainWindow : Window
{
public MainWindow ()
{
InitializeComponent ();
this.DataContext = new MyViewModel ();
}
}
I used Nuget Package Manager to pull the required dll's for Cinch
, System.Windows.Interactivity
and Microsoft.Expression.Interactions
Upvotes: 1
Reputation: 1000
The confusion is Button control's default click event shadows over other events like double click, mouse down etc. So May be using a Label is a good idea. You can camouflage it as a button and then use MouseDown and MouseDoubleClick events of the label to do your two different tasks. Use a timer to differentiate single click. Following link shows more detail
Upvotes: 0