Reputation: 259
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?
Upvotes: 4
Views: 8527
Reputation: 178660
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 TogglingCommand : ICommand
{
private readonly ICommand _command1;
private readonly ICommand _command2;
private ICommand _activeCommand;
public TogglingCommand(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 TogglingCommand
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.
Upvotes: 4
Reputation: 38365
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");
}
}
Upvotes: 0