Is there a way I can attach a handler (callback) in buttons of my control (which eventually execute the ICommand
) so that my control knows when a command execution is completed?
You can create abstract CallbackableCommand that would raise callback method.
abstract class CallbackableCommand : ICommand
{
private IInputElement getRaisedElement()
{
return Keyboard.FocusedElement;
}
public void Execute(object parameter)
{
ExecuteImpl(parameter);
var element = getRaisedElement();
if(element == null) return;
//var ci = typeof(ExecutedRoutedEventArgs).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
//var routedEventArgs = (RoutedEventArgs)ci.Invoke(new object[] { this, parameter });
var routedEventArgs = new RoutedEventArgs();
//routedEventArgs.RoutedEvent = CommandManager.ExecutedEvent;
routedEventArgs.RoutedEvent = Callbackable.CommandExecutedEvent;
routedEventArgs.Source = element;
routedEventArgs.Handled = false;
element.RaiseEvent(routedEventArgs);
}
public abstract void ExecuteImpl(object parameter);
abstract public bool CanExecute(object parameter);
abstract public event EventHandler CanExecuteChanged;
}
Inherit your command from CallbackableCommand and override CanExecute, CanExecuteChanged and ExecuteImpl(instead of Execute)
class SimpleCommand : CallbackableCommand
{
public override void ExecuteImpl(object parameter)
{
MessageBox.Show("Simple command execute with parameter: "
+ parameter ?? "null");
}
public override bool CanExecute(object parameter)
{
return true;
}
public override event EventHandler CanExecuteChanged;
}
Own element to specify CommandExecuted
event:
public class Callbackable : ContentControl
{
public static readonly RoutedEvent CommandExecutedEvent = EventManager.RegisterRoutedEvent(
"CommandExecuted", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Callbackable));
// Provide CLR accessors for the event
public event RoutedEventHandler CommandExecuted
{
add { AddHandler(CommandExecutedEvent, value); }
remove { RemoveHandler(CommandExecutedEvent, value); }
}
}
Edit:
In your control specify Callbackable.CommandExecuted
event
<Grid>
<Grid.Resources>
<local:SimpleCommand x:Key="btnCommand" />
</Grid.Resources>
<local:Callbackable>
<Button Command="{StaticResource btnCommand}"
CommandParameter="param"
local:Callbackable.CommandExecuted="Button_Executed" >
Click me
</Button>
</local:Callbackable>
</Grid>
Executed event handler:
private void Button_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Executed");
}