views:

953

answers:

2

Hello, I am looking for a way to be able to have an event run after a command executes. I am working with EditingCommands (ToggleBold, ToggleItalic...ect.) and would like to be able to have a method called directly after the command finishes whatever it is doing. An example would be that I have some text selected and press Ctrl+B and that executes EditingCommands.ToggleBold. Right after the text is toggled I want to call an method that will update a ToggleButton that is connected with the selection FontWeight. I tried using the Executed event but that is unfortunately for me called before the text is affected and consequently updates the button with information that will change in just a second. Does anyone know a way around this? Thank you for any help!

Cheers

A: 

Can you use the Executed (past tense) Routed Event handler? (Or maybe that's what you're saying you tried)

public partial class CustomerWindow : Window
{
    public CustomerWindow()
    {
        InitializeComponent();

        CommandBinding binding = new CommandBinding(ApplicationCommands.Copy);
        binding.Executed += new ExecutedRoutedEventHandler(this.copy_Executed);
        this.CommandBindings.Add(binding);
    }

    void copy_Executed(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("Executed the Copy command");
    }
}
AaronLS
This is what I was trying. As I mentioned in a comment to the answer by Kent, this doesn't work because it seems to override the default EditingCommands even with e.Handled = false;
Jasson
+2  A: 

A workaround is to queue another message in your Executed handler:

void copy_Executed(object sender, EventArgs e)
{
    Dispatcher.BeginInvoke(new ThreadStart(delegate()
    {
        //do update of bold button here
    }), null);
}

This will ensure your work is added to the back of the queue, and will be executed after other messages of the same or higher priority.

However, I'd like to suggest a better solution. If you think about it, the bold button is responsible for executing two different commands: make bold, and make normal. It switches between these two commands based on the currently selected text/caret position. Therefore, you could write a custom ICommand implementation that encapsulates two sub-commands (completely untested code):

public class CompositeCommand : ICommand
{
    private readonly ICommand _command1;
    private readonly ICommand _command2;
    private ICommand _activeCommand;

    public CompositeCommand(ICommand command1, ICommand command2)
    {
        _command1 = command1;
        _command2 = command2;
    }

    public ICommand ActiveCommand
    {
        get { return _activeCommand; }
    }

    public bool CanExecute(object parameter)
    {
        if (_command1.CanExecute(parameter))
        {
            _activeCommand = _command1;
        }
        else if (_command2.CanExecute(parameter))
        {
            _activeCommand = _command2;
        }
        else
        {
            _activeCommand = null;
        }

        return _activeCommand != null;
    }

    public void Execute(object parameter)
    {
        _activeCommand.Execute(parameter);
    }
}

You can then construct a CompositeCommand with two commands: one to bolden and one to unbolden text. Then you can bind the Button in your UI to the ActiveCommand property to change it in anyway you like based on what will happen when you click the command. For example, if you're using a ToggleButton you would bind IsChecked to ActiveCommand and convert to true is the active command is unbolden. Of course, the bolden and unbolden commands need CanExecute logic of their own that inspects the selected text.

HTH, Kent

Kent Boogaart
Thanks Kent. I found out that my real problem is that when I set the Executed handler of one of these EditingCommands it will not call their default one. I didn't notice this because I had the CommandBindings set in the Grid and not RichTextBox so they weren't working. I will just implement them.
Jasson