SHARE
Facebook X Pinterest WhatsApp

Implement a Command Pattern Using C#

Implement a Command Pattern Using C# With Visual Studio.NET IDE, one can easily add user interface objects such as menus and toolbar buttons to a form and let the IDE generate event handlers skeleton code in the form’s design window to handle the events triggered by pressing toolbar buttons or selecting menus. Although this automatic […]

Written By
thumbnail
CodeGuru Staff
CodeGuru Staff
Nov 25, 2008
CodeGuru content and product recommendations are editorially independent. We may make money when you click on links to our partners. Learn More

Implement a Command Pattern Using C#

With Visual Studio.NET IDE, one can easily add user interface objects such as menus and toolbar buttons to a form and let the IDE generate event handlers skeleton code in the form’s design window to handle the events triggered by pressing toolbar buttons or selecting menus. Although this automatic code generation makes the user interface design and coding very easy, for a large, complex Windows application, a great amount of event handling code is dumped into the form class and makes the form class code increasingly bulky and difficult to maintain. From the viewpoint of object-oriented design, this is also not a very good design and the code cannot be re-used.

Buttons or menu items usually carry out a request in response to user input, which then causes an action to be invoked. The command design pattern lets these user interface objects make requests of unspecified application objects by turning the request itself into an object. This object can be stored and passed around like other objects. This separation of user interface objects from the receivers of the requests makes the code easy to maintain and promotes code re-use.

This article gives an example of an implementation of the Command pattern using C# in a Windows application.

The Application

The application is just for demo purposes and therefore it is not a real-world one. It is a simple text editor with Open File and Save File menu items in the File menu; and Copy, Cut, and Paste menu items in the Edit menu. It also has Open File, Save File, Copy, and Paste tool strip buttons. Each of these user interface objects has a reference to a command object that is derived from an abstract base command class. When a click event is triggered, the user interface object invokes the Execute method of the concrete command object. The concrete command class has a reference to an editor object and delegate the task to the editor object. A concrete command object is created by a command factory that provides factory methods for each concrete command class.

The Text Editor Class

The TextEditor class contains a Windows textbox and methods to open and save a text file and copy, cut, and and paste text in the text box. The TextEditor also handles the shortcut keys Ctrl+X for cut, Ctrl+V for paste, and Ctrl+Z for undo. When it receives a Ctrl+X or Ctrl+V shortcut key, it creates a Cut or Paste command object and pushes it to a command stack owned by an undo command object for a possible undo operation later on. Therefore, the TextEditor also has a reference to the command factory and undo command object. I’ll discuss the command factory and undo command later.

public class TextEditor
{
   private CmdFactory _factory;
   private UndoCmd _undoCmd;
   private TextBox _textBox;
   private OpenFileDialog _openFileDlg;
   private string _filePath;

   public TextEditor(TextBox textBox)
   {
      _textBox = textBox;
      _undoCmd = null;
      _openFileDlg = new OpenFileDialog();
      this._textBox.KeyDown +=
         new System.Windows.Forms.
         KeyEventHandler(this.TextBoxKeyDown);
   }

   // Properties, methods, and KeyDown event handler below.

}

The Command Factory Class

The CmdFactory command factory class has a reference to TextEditor and provides factory methods to produce command objects.

public class CmdFactory
{
   private TextEditor _editor;

   public CmdFactory(TextEditor editor)
   {
      _editor = editor;
      _editor.CmdFactory = this;
   }

   public OpenFileCmd OpenFileCmd()
   {
      return new OpenFileCmd(_editor, this);


   }

   public SaveFileCmd SaveFileCmd()
   {
      return new SaveFileCmd(_editor, this);
   }

   public UndoCmd UndoCmd(CmdMenuItem undoMenuItem)
   {
      return new UndoCmd(_editor, this, undoMenuItem);
   }

   public CopyCmd CopyCmd()
   {
      return new CopyCmd(_editor, this);
   }

   public CutCmd CutCmd()
   {
      return new CutCmd(_editor, this);
   }

   public PasteCmd PasteCmd()
   {
      return new PasteCmd(_editor, this);
   }
}

The Base Class of the Command Classes

The BaseCmd class is the base class of all other command classes. It has references to TextEditor and CmdFactory objects and an abstract method, Execute().

abstract public class BaseCmd
{
   protected TextEditor _editor;
   protected CmdFactory _factory;
   abstract public void Execute();

   public BaseCmd(TextEditor editor, CmdFactory factory)
   {
      _editor = editor;
      _factory = factory;
   }
}

The Concrete Command Classes That Do Not Support Undo

Generally, concrete command classes override the Execute() abstract method of the base class and delegate the operation to TextEditor. Some concrete commands do not support undo operation; for example, open/save file commands, and the copy command. These command classes are directly derived from the BaseCmd class.

public class OpenFileCmd : BaseCmd
{
   public OpenFileCmd(TextEditor editor, CmdFactory factory)
      : base(editor, factory)
   {
   }

   // Delegate Execution operation to OpenFile operation
   // of TextEditor.
   public override void Execute()
   {
      _editor.OpenFile();
   }
}

public class SaveFileCmd : BaseCmd
{
   public SaveFileCmd(TextEditor editor, CmdFactory factory)
      : base(editor, factory)
   {
   }

   public override void Execute()
   {
      _editor.SaveFile();
   }
}

public class CopyCmd : BaseCmd
{
   public CopyCmd(TextEditor editor, CmdFactory factory)
      : base(editor, factory)
   {
   }

   public override void Execute()
   {
      _editor.Copy();
   }
}

Concrete Command Classes That Support Undo Operation

The cut and paste command supports the undo operation. They are derived from the UndoableCmd class that is an abstract class itself and is in turn derived from the BaseCmd class. UndoableCmd has an abstract property, Name, and an abstract method, Undo().

abstract public class UndoableCmd : BaseCmd
{
   public UndoableCmd(TextEditor editor, CmdFactory factory)
      : base(editor, factory)
   {
   }

   abstract public string Name { get; }
   abstract public void Undo();
}

A concrete undoable command class is derived from the UndoabldCmd class. It overrides the Execute() abstract method of the BaseCmd class and the Undo() abstract method of the UndoableCmd class. Here, you take the CutCmd class for the cut command as an example.

public class CutCmd : UndoableCmd
{
   private int _selStart;
   private string _selText;

   public CutCmd(TextEditor editor, CmdFactory factory)
      : base(editor, factory)
   {
      _selStart = editor.SelectionStart;
      _selText = editor.SelectedText;
   }

   public override string Name
   {
      get { return "Cut"; }
   }

   public override void Execute()
   {
      CutCmd cmd = _factory.CutCmd();
      _editor.Cut(cmd);
   }

   public override void Undo()
   {
      _editor.UndoCut(_selStart, _selText);
   }
}

Note In the Execute() method of CutCmd, a new instance of CutCmd is created by the command factory. The method calls TextEditor's Cut() method, passing this CutCmd object as the parameter. This is because with each "cut" operation, a CutCmd object needs to be pushed into the command stack of the Undo command object for a possible undo operation. The Cut() method of TextEditor shows how it is accomplished:

// Cut() method of TextEditor
public void Cut(CutCmd cmd)
{
   _textBox.Cut();
   _undoCmd.Push(cmd);
}

Recommended for you...

Different Types of JIT Compilers in .NET
Tariq Siddiqui
Mar 17, 2023
Middleware in ASP.NET Core
Tariq Siddiqui
Mar 16, 2023
Intro to Intel oneDAL and ML.NET
Hannes DuPreez
Jan 16, 2023
Types of Query Execution in LINQ
Tariq Siddiqui
Dec 15, 2022
CodeGuru Logo

CodeGuru covers topics related to Microsoft-related software development, mobile development, database management, and web application programming. In addition to tutorials and how-tos that teach programmers how to code in Microsoft-related languages and frameworks like C# and .Net, we also publish articles on software development tools, the latest in developer news, and advice for project managers. Cloud services such as Microsoft Azure and database options including SQL Server and MSSQL are also frequently covered.

Property of TechnologyAdvice. © 2025 TechnologyAdvice. All Rights Reserved

Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.