Есть ли способ получить обратный вызов, когда элемент управления (например, кнопка) завершает выполнение ICommand? - PullRequest
0 голосов
/ 13 октября 2011

У меня есть пользовательский элемент управления, который принимает свойства зависимости ICommand, позволяя ВМ указать команду.

Есть ли способ, которым я могу прикрепить обработчик (обратный вызов) к кнопкам моего элемента управления (которые в конечном итоге выполняютICommand) чтобы мой орган управления знал, когда выполнение команды завершено?

Спасибо за проявленный интерес.

1 Ответ

0 голосов
/ 13 октября 2011

Вы можете создать абстрактную CallbackableCommand, которая вызовет метод обратного вызова.

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;
  }

Унаследовать вашу команду от CallbackableCommand и переопределить CanExecute, CanExecuteChanged и ExecuteImpl (вместо 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;
  }

Свой элемент для указания CommandExecuted событие:

  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: В вашем контроле укажите Callbackable.CommandExecuted событие

<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>

Выполненный обработчик событий:

private void Button_Executed(object sender, ExecutedRoutedEventArgs e)
{
  MessageBox.Show("Executed");
}
...