How to: Bind a Command to a Button in the Rich Text Editor for WinForms
- 5 minutes to read
A command can be bound to virtually any UI element. This example demonstrates a simple case - how to bind the UndoCommand command to a SimpleButton control.
Description
First, we create a descendant of the SimpleButton class, named CommandButton. Then, add two fields which will distinguish it from a simple button - one field to hold a Command object, the other - to hold a RichEditControl. Add corresponding properties with getters and setters.
The Initialize method will perform an initial assignment of the control and command identifier, both of which are required to create a command for the command button. The command itself is obtained in the CreateCommand method.
Note
You should always create a new instance of a command before execution.
Subscribe to the RichEditControl.UpdateUI event of the RichEditControl to be notified about changes affecting the control’s user interface. The handler for this event should be able to update the UI for the command. We name this method “OnUpdateUI“. Notice that setters for the Command and RichEditControl properties should also call the OnUpdateUI method.
To update the command UI we need an object representing the command UI state of our CommandButton. Let’s name it CommandButtonUIState. It inherits from the ICommandUIState interface and implements the ICommandUIState.Checked, the ICommandUIState.Enabled and theICommandUIState.Visible properties. The OnUpdateUI method creates a command instance, the CommandButtonUIState instance and updates the command UI state by calling the command’s Command.UpdateUIState method.
The setter for the Command property calls the OnUpdateUI method. The setter for the RichEditControl property unsubscribes from the RichEditControl.UpdateUI event before assignment, then subscribes back to UpdateUI event and calls the OnUpdateUI method.
The final step is to override the OnClick method in our SimpleButton descendant. When a CommandButton is clicked, it will create a command object instance and execute a command by calling its Command.Execute method.
Implementation
The following code demonstrates the implementation of the technique described above:
public class CommandButton : SimpleButton {
RichEditCommandId commandId;
RichEditControl control;
public void Initialize(RichEditControl initControl,RichEditCommandId initId)
{
UnsubscribeControlEvents();
control = initControl;
commandId = initId;
SubscribeControlEvents();
}
public RichEditControl RichEditControl {
get { return control; }
set {
if(control == value)
return;
UnsubscribeControlEvents();
this.control = value;
SubscribeControlEvents();
OnUpdateUI(this, EventArgs.Empty);
}
}
public RichEditCommandId CommandId
{
get { return commandId; }
set {
if (commandId == value)
return;
commandId = value;
OnUpdateUI(this, EventArgs.Empty);
}
}
void SubscribeControlEvents() {
if(control == null)
return;
control.UpdateUI += OnUpdateUI;
}
void UnsubscribeControlEvents() {
if(control == null)
return;
control.UpdateUI -= OnUpdateUI;
}
void OnUpdateUI(object sender, EventArgs e) {
Command command = CreateCommand();
if(command != null) {
CommandButtonUIState state = new CommandButtonUIState(this);
command.UpdateUIState(state);
}
}
protected override void OnClick(EventArgs e) {
base.OnClick(e);
Command command = CreateCommand();
if(command != null)
command.Execute();
}
// You may override this method to create a command
protected virtual Command CreateCommand() {
return control.CreateCommand(commandId);
}
}
public class CommandButtonUIState : ICommandUIState {
readonly SimpleButton button;
public CommandButtonUIState(SimpleButton button) {
this.button = button;
}
#region ICommandUIState Members
public bool Checked { get { return false; } set {} }
public bool Enabled { get { return button.Enabled; } set { button.Enabled = value; } }
public bool Visible { get { return button.Visible; } set { button.Visible = value; } }
public virtual object EditValue { get { return null; } set { } }
}
Usage
Command Adapter Technique
The Command Button technique seems rather straightforward, although it has its own drawbacks. It forces us to create as many descendant classes as there are user interface elements for which command binding is required. The next step is implementing a Command Adapter object which can serve as a helpful generalization of a command UI binding solution. A command adapter contains an additional field representing a UI element, the SimpleButton in our case. The CommandButtonAdapter implementation is demonstrated in the CodeCentral example.