Back to Devexpress

How to: Bind a Command to a Button in the Rich Text Editor for WinForms

windowsforms-7071-controls-and-libraries-rich-text-editor-examples-commands-how-to-bind-a-command-to-a-button.md

latest9.7 KB
Original Source

How to: Bind a Command to a Button in the Rich Text Editor for WinForms

  • Nov 28, 2023
  • 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:

csharp
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);
    }
}
vb
Public Class CommandButton
    Inherits SimpleButton
    Private commandId_Renamed As RichEditCommandId
    Private control As RichEditControl

    Public Sub Initialize(ByVal initControl As RichEditControl, ByVal initId As RichEditCommandId)
        UnsubscribeControlEvents()
        control = initControl
        commandId_Renamed = initId
        SubscribeControlEvents()
    End Sub

    Public Property RichEditControl() As RichEditControl
        Get
            Return control
        End Get
        Set(ByVal value As RichEditControl)
            If control Is value Then
                Return
            End If
            UnsubscribeControlEvents()
            Me.control = value
            SubscribeControlEvents()
            OnUpdateUI(Me, EventArgs.Empty)
        End Set
    End Property
    Public Property CommandId() As RichEditCommandId
        Get
            Return commandId_Renamed
        End Get
        Set(ByVal value As RichEditCommandId)
            If commandId_Renamed = value Then
                Return
            End If
            commandId_Renamed = value
            OnUpdateUI(Me, EventArgs.Empty)
        End Set
    End Property

    Private Sub SubscribeControlEvents()
        If control Is Nothing Then
            Return
        End If
        AddHandler control.UpdateUI, AddressOf OnUpdateUI
    End Sub
    Private Sub UnsubscribeControlEvents()
        If control Is Nothing Then
            Return
        End If
        RemoveHandler control.UpdateUI, AddressOf OnUpdateUI
    End Sub

    Private Sub OnUpdateUI(ByVal sender As Object, ByVal e As EventArgs)
        Dim command As Command = CreateCommand()
        If command IsNot Nothing Then
            Dim state As New CommandButtonUIState(Me)
            command.UpdateUIState(state)
        End If
    End Sub

    Protected Overrides Sub OnClick(ByVal e As EventArgs)
        MyBase.OnClick(e)
        Dim command As Command = CreateCommand()
        If command IsNot Nothing Then
            command.Execute()
        End If
    End Sub

    ' You may override this method to create a command
    Protected Overridable Function CreateCommand() As Command

        Return control.CreateCommand(commandId_Renamed)
    End Function
End Class
csharp
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 { } }  
}
vb
Public Class CommandButtonUIState
    Implements ICommandUIState
    Private ReadOnly button As SimpleButton
    Public Sub New(ByVal button As SimpleButton)
        Me.button = button
    End Sub
    #Region "ICommandUIState Members"
    Public Property Checked() As Boolean Implements ICommandUIState.Checked
        Get
            Return False
        End Get
        Set(ByVal value As Boolean)
        End Set
    End Property
    Public Property Enabled() As Boolean Implements ICommandUIState.Enabled
        Get
            Return button.Enabled
        End Get
        Set(ByVal value As Boolean)
            button.Enabled = value
        End Set
    End Property
    Public Property Visible() As Boolean Implements ICommandUIState.Visible
        Get
            Return button.Visible
        End Get
        Set(ByVal value As Boolean)
            button.Visible = value
        End Set
    End Property
    Public Overridable Property EditValue() As Object Implements ICommandUIState.EditValue
        Get
            Return Nothing
        End Get
        Set(ByVal value As Object)
        End Set
    End Property

Usage

csharp
btnUndo.Initialize(richEditControl1, RichEditCommandId.Undo);
vb
btnUndo.Initialize(richEditControl1, RichEditCommandId.Undo)

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.