Category Archives: Basic

Prototype Pattern

Clonomat

Sometimes the creation of new objects is time and resource intensive. You could create a thousand objects during the program initialization and park them on a queue. The object would then be ready when needed. And looking at the Garbage Collection process in more detail, you may notice that the Generation has probably changed by then. Your object requires less processor time the older it becomes.

But this is not the topic today. It just has a similar idea. We are talking about time and/or resource intensive object creation.

The Prototype Pattern is used for cloning objects. Cloning can be substantially faster than initializing objects from scratch. Let’s say object A did load a lot of data from a file. You don’t have to do the same for object B. Simply copy object A and amend some fields.

Here is the pattern:

public interface IChocolateBar {
  IChocolateBar Clone();
} // interface

public class MintChocolateBar : IChocolateBar {
  public readonly int ObjectNumber;
  public MintChocolateBar(int xObjectNumber) { ObjectNumber = xObjectNumber; }

  public IChocolateBar Clone() { return MemberwiseClone() as MintChocolateBar; } 
} // class

public class DarkChocolateBar : IChocolateBar {
  public readonly int ObjectNumber;
  public DarkChocolateBar(int xObjectNumber) { ObjectNumber = xObjectNumber; }

  public IChocolateBar Clone() { return MemberwiseClone() as DarkChocolateBar; } 
} // class

public class CloneFactory {
  public IChocolateBar get(IChocolateBar xChocolateBar) { return xChocolateBar.Clone(); } 
} // class

The pattern is not really satisfying. Is there something better? C# offers the ICloneable interface.

public class Shortcut : ICloneable  {
  public readonly int ObjectNumber;
  public Shortcut(int xObjectNumber) { ObjectNumber = xObjectNumber; }

  public object Clone() { return MemberwiseClone(); } 
} // class

The problem with this interface is the missing generic type. In fact the use is obsolete and Microsoft does not recommend it anymore. We therefore build our own implementation.

public class Shortcut2 {
  public readonly int ObjectNumber;
  public Shortcut2(int xObjectNumber) { ObjectNumber = xObjectNumber; }

  public Shortcut2 ShallowCopy() { return MemberwiseClone() as Shortcut2; } 
} // class

Using an interface like

interface IShallowCopy<T> {
  T IShallowCopy();
} // interface 

public class Shortcut3<T> : IShallowCopy<T> {
  public readonly int ObjectNumber;
  public Shortcut3(int xObjectNumber) { ObjectNumber = xObjectNumber; }

  public T ShallowCopy() { return MemberwiseClone() as T; } 
} // class

is nonsense. You cannot compile and instantiate this.
What else could we do? A static clone method quickly leads us back to a factory similar type. Hence we end up with something that we were having at the very beginning today. Just keep your solutions generic and you should be fine with this pattern.

MemberwiseClone()

We were using MemberwiseClone() to keep the example source code simple. The following is important to know:

MemberwiseClone() is a shallow copy. If a field of the copied object is a reference type, the reference is copied but the referred object is not; therefore, the original object and its clone refer to the same object.

To avoid the same references in the clone, you have to write your own Deep Copy or Lazy Copy. Your clone method must clone the object and objects inside the object.

A practical example:

Stock exchange orders need to be sent with a minimal delay. The fight for nanoseconds is tremendous. Companies even shorten the physical server cables to the exchanges in order to increase speed. One foot in length equals roughly one nanosecond these days.
The object creation for orders takes too long in the proprietary business. It is meaningful to generate orders before any decision is made. The next order sits in a queue of clones. When the machine decides to trade, then the order is taken from that queue and a few fields are populated/overridden. These are eg. trade size and price. There is no memory allocation at this late stage. As said, each nanosecond counts.

Full source code

Notice that

Console.WriteLine("ObjectNumber = " + lMintClone.ObjectNumber); 

prints the same number as the original object. There are two objects at two locations in the RAM. Therefore the HashCode is different. Still the field content is the same.

using System;

namespace PrototypePattern {

  public interface IChocolateBar {
    IChocolateBar Clone();
  } // interface

  public class MintChocolateBar : IChocolateBar {
    public readonly int ObjectNumber;
    public MintChocolateBar(int xObjectNumber) { ObjectNumber = xObjectNumber; }

    public IChocolateBar Clone() { return MemberwiseClone() as MintChocolateBar; }

  } // class

  public class DarkChocolateBar : IChocolateBar {
    public readonly int ObjectNumber;
    public DarkChocolateBar(int xObjectNumber) { ObjectNumber = xObjectNumber; }

    public IChocolateBar Clone() { return MemberwiseClone() as DarkChocolateBar; }

  } // class

  public class CloneFactory {
    public IChocolateBar get(IChocolateBar xChocolateBar) { return xChocolateBar.Clone(); }
  } // class


  // IClonable is non-generic
  public class Shortcut : ICloneable {
    public readonly int ObjectNumber;
    public Shortcut(int xObjectNumber) { ObjectNumber = xObjectNumber; }

    public object Clone() { return MemberwiseClone(); } 
  } // class

  public class Shortcut2 {
    public readonly int ObjectNumber;
    public Shortcut2(int xObjectNumber) { ObjectNumber = xObjectNumber; }

    public Shortcut2 ShallowCopy() { return MemberwiseClone() as Shortcut2; } 
  } // class

  class Program {

    static void Main(string[] args) {
      CloneFactory lCloneFactory = new CloneFactory();
      MintChocolateBar lMint = new MintChocolateBar(1);
      MintChocolateBar lMintClone = lCloneFactory.get(lMint) as MintChocolateBar;
      Console.WriteLine("Original object: ");
      Console.WriteLine("HashCode = " + lMint.GetHashCode());
      Console.WriteLine("ObjectNumber = " + lMint.ObjectNumber);
      Console.WriteLine();
      Console.WriteLine("Clone: ");
      Console.WriteLine("HashCode = " + lMintClone.GetHashCode());
      Console.WriteLine("ObjectNumber = " + lMintClone.ObjectNumber);  // !!!
      Console.WriteLine();
      Console.WriteLine("Are the objects the same? " + (lMint == lMintClone));

      DarkChocolateBar lDark = new DarkChocolateBar(2);
      DarkChocolateBar lDarkClone = lCloneFactory.get(lDark) as DarkChocolateBar;
      Console.WriteLine();
      Console.WriteLine();
      Console.WriteLine();
      Console.WriteLine("Dark chocolate: ");
      Console.WriteLine("Are the objects the same? " + (lMint == lMintClone));


      // old school
      Shortcut lShort = new Shortcut(3);
      Shortcut lShortClone = lShort.Clone() as Shortcut;
      Console.WriteLine();
      Console.WriteLine("ICloneable: ");
      Console.WriteLine("Are the objects the same? " + (lShort == lShortClone));

      Console.ReadLine();
    } //

  } // class

} // namespace

example output:
Original object:
HashCode = 62125865
ObjectNumber = 1

Clone:
HashCode = 44200505
ObjectNumber = 1

Are the objects the same? False

Dark chocolate:
Are the objects the same? False

ICloneable:
Are the objects the same? False

Wikipedia

Advertisements

Builder Pattern

Car

Who does not know the StringBuilder in namespace System.Text?
The purpose of the StringBuilder is to construct a string much faster than using the operator overload “+”. Strings are immutable. Each time you use the overloaded operator, a new object is created. That slows down the creation of the final object. Here is a quick benchmark:

using System;
using System.Diagnostics;
using System.Text;

namespace demo {
  class Program {

    static void Main(string[] args) {
      Stopwatch lStopwatch = new Stopwatch();
      lStopwatch.Start();
      string s = "";
      for (int i = 0; i < 100000; i++) s += "x";
      lStopwatch.Stop();
      Console.WriteLine("Operator, elapsed ms: " + lStopwatch.ElapsedMilliseconds);

      StringBuilder lStringBuilder = new StringBuilder();
      lStopwatch.Restart();
      for (int i = 0; i < 100000; i++) lStringBuilder.Append("x");
      lStopwatch.Stop();
      Console.WriteLine("StringBuilder, elapsed ms: " + lStopwatch.ElapsedMilliseconds);

      Console.ReadLine();
    } //

  } // class
} // namespace

example output:
Operator, elapsed ms: 3029
StringBuilder, elapsed ms: 1

The StringBuilder supports method chaining. You can shorten your source code and write:

string s = new StringBuilder()
  .Append("a")
  .Append("b")
  .Append("c")
  .Append("d")
  .ToString();

instead of

StringBuilder lStringBuilder = new StringBuilder();
lStringBuilder.Append("a");
lStringBuilder.Append("b");
lStringBuilder.Append("c");
lStringBuilder.Append("d");
string s = lStringBuilder.ToString();

In general the purpose of a Builder is to separate complex object construction from its representation.

We leave the idea of strings behind and build something entirely different. This time it is not about speed, it is more about avoiding thousands of parameters in constructors and making complexity look a little bit easier. Two weeks ago I was using BMW AG to give an example for an Abstract Factory. Let’s stay loyal to cars and build classes for the production assembly.

using System;

namespace demo {

  [Flags]
  public enum eRadio { GPS = 1, MP3 = 2, Screen = 4, Phone = 8 }
  public enum eColor { NotSet = 0, Silver, Red, Blue, White, Black }

  class Program {

    public class Car {
      public readonly eRadio Radio;
      public readonly eColor Color;
      public readonly double Displacement;
      public readonly int Doors;
      public readonly bool Hatchback;
      public readonly bool LeatherSeats;

      internal Car(eRadio xRadio, eColor xColor, double xDisplacement, int xDoors, bool xHatchback, bool xLeatherSeats) {
        Radio = xRadio;
        Color = xColor;
        Displacement = xDisplacement;
        Doors = xDoors;
        Hatchback = xHatchback;
        LeatherSeats = xLeatherSeats;
      } // constructor

    } // class

    public class CarBuilder {

      private eRadio _Radio = 0;
      private eColor _Color = eColor.NotSet;
      private double _Displacement = 0.0;
      private uint _Doors = 1;
      private bool? _Hatchback = null;
      private bool? _LeatherSeats = null;

      internal CarBuilder SetColor(eColor xValue) { _Color = xValue; return this; }
      internal CarBuilder SetDisplacement(double xValue) { _Displacement = xValue; return this; }
      internal CarBuilder SetDoors(uint xValue) { _Doors = xValue; return this; }
      internal CarBuilder SetHatchback(bool xValue) { _Hatchback = xValue; return this; }
      internal CarBuilder SetRadio(eRadio xValue) { _Radio = xValue; return this; }
      internal CarBuilder SetLeatherSeats(bool xValue) { _LeatherSeats = xValue; return this; }
      internal Car Create() {
        if (_Hatchback == null) throw new Exception("Hatchback not set");
        if (_LeatherSeats == null) throw new Exception("LeatherSeats not set");
        if (_Doors < 1 || _Doors > 6) throw new Exception("number of Doors invalid");
        // ... etc.

        return new Car(_Radio, _Color, _Displacement, (int)_Doors, (bool)_Hatchback, (bool)_LeatherSeats);
      }
    } // class

    static void Main(string[] args) {

      Car lCar = new CarBuilder()
        .SetColor(eColor.Silver)
        .SetDisplacement(2.2)
        .SetDoors(5)
        .SetHatchback(true)
        .SetRadio(eRadio.GPS | eRadio.MP3 | eRadio.Screen)
        .SetLeatherSeats(true)
        .Create();

      Console.ReadLine();
    } // main

  } // class
} // namespace

http://en.wikipedia.org/wiki/Builder_pattern

Adapter Pattern

Adapter
Once again it sounds more difficult than it actually is.

What is an Adapter?

An Adapter sits in between two objects that cannot be changed and cannot talk to each other. It is like the American and British power socket:

  • The socket shape and voltage are different.
  • You cannot change the situation. The source and the target are static.
  • An adapter can connect the two systems.

Adapters can also connect to several source or target objects. Let’s imagine a database is split in two. An Adapter could connect to the two separate databases and return the result as if it was just one. Using several source objects is uncommon. It does make sense, when events from two or more sources need to occur before the access to the target object can take place.

MultiAdapter

I’d say that the Adapter pattern is not more than a workaround, it is a compromise to avoid other problems. There is a difference between chewing gum and glue. Both can hold pieces together … somehow.
Imagine a British datacenter with 1000 (US->UK) power socket adapters. It would work, but don’t wonder, when someone stumbles over a adapter and disconnects something important.

(The WPF value converter is similar, not the same though. The converter eg. accepts a string and returns a double.)

Here is a short example:

namespace demo {

  public interface IPrinterDriver {
    void Print(string xText);
  } // interface

  // Client
  public class PrinterDriver : IPrinterDriver {
    private readonly IPrinterDriver _Driver;
    public PrinterDriver(IPrinterDriver xDriver) { _Driver = xDriver; }

    public void Print(string xText) { _Driver.Print(xText); }
  } // class

  // Adaptee
  public class Windows3_1_MatrixPrinterDriver {
    public void Init(string xCommandSequence) { ... }
    public void ParkPrintHead() { ... }
    public void Print(string xText) { ... }
  } // class

  // Adapter
  public class Win8_to_Win31_PrinterDriverAdapter : IPrinterDriver {
    private readonly Windows3_1_MatrixPrinterDriver _Driver = new Windows3_1_MatrixPrinterDriver();
    public void Print(string xText) {
      _Driver.Init("§50asabpwebts.dae§");
      _Driver.Print(xText);
      _Driver.ParkPrintHead();
    } //
  } // class

  class Program {

    static void Main(string[] args) {
      Win8_to_Win31_PrinterDriverAdapter lAdapter = new Win8_to_Win31_PrinterDriverAdapter();
      PrinterDriver lDriver = new PrinterDriver(lAdapter);
      lDriver.Print("Hello World!");
    } //

  } // class
} // namespace

In many examples the adapter inherits the Adaptee AND the Interface, which would then look like this:

public class Win8_to_Win31_PrinterDriverAdapter : IPrinterDriver, Windows3_1_MatrixPrinterDriver { ... }

I disagree with such approach and rather use create a private readonly field instead. It is easier to avoid naming conflicts then.

Abstract Factory Pattern

BMW

 

There are many definitions on the internet of what the factory pattern would/should be. It is important to comply with your professor while you study at a university. Besides that programming is an art. It has nothing to do with naming conventions. Mona Lisa could be named Paul, you see. Only posh people care about technique naming. But if you paint a picture yourself, you don’t care about any technique naming convention at all; you only care about your results. And if people like it, then you are successful. It is the same with programming.

The Factory Method Pattern usually refers to a class that creates just one type of object.
The Abstract Factory Pattern usually refers to a class that can create various types of objects, which have something in common.

Besides that we have a lot of gibberish about some 10 and more years old pattern.

I could add a lot of code here, but it should suffice to just get the idea of it. Have a look at the above picture. An abstract class/interface is used as the base class for country specific factories. These factories create the objects.
The Z4 Model is built in Germany and China (just for demonstration purposes). Basically they are the same besides the difference between the Chinese and German regulations.

Now, translate that to your own business case. You may need a Factory that creates code for your Unix, Mac, and Windows system. On top of that you may have to create two distinct objects for your test and prod environment.

Other explanations are here or here.

Factory pattern

Factory

 

Life was so easy. Why do we have to make it worse now and implement a so-called “Factory”?

Dependency Injection is about using abstract classes and interfaces to avoid concrete classes. Therefore the creation of a concrete class like “new Ferrari()” violates the idea of flexibility and dependency injection. The Factory Pattern allows us to instantiate concrete classes while depending only on abstract classes/interfaces. The development process becomes much easier in an environment where concrete classes are changing frequently.

using System;

namespace demo {

  public abstract class Car { public string Name { get; protected set; } }
  public class Ferrari : Car { public Ferrari() { Name = "Red Speeder"; } }
  public class VW : Car { public VW() { Name = "German Classic"; } }
  public class Fiat : Car { public Fiat() { Name = "White Something"; } }

  public interface ICarFactory {
    Car GetObjectExpensive();
    Car GetObjectCheap();
  } // interface

  public class CarFactory : ICarFactory {
    public Car GetObjectExpensive() { return new Ferrari(); }
    public Car GetObjectCheap() { return new Fiat(); }
  } // class

  public class DependentClass {
    public readonly Car car = new Ferrari();
  } // class

  public class IndependentClass {
    public readonly Car car;
    public IndependentClass(Car xCar) {
      car = xCar;
    } // constructor
  } // class

  class Program {
    static void Main(string[] args) {
      DependentClass d = new DependentClass();
      CarFactory lCarFactory = new CarFactory();
      IndependentClass i = new IndependentClass(lCarFactory.GetObjectExpensive());
      Console.WriteLine(i.car.Name); // Red Speeder
      Console.ReadLine();
    } // main
  } // class

} // namespace

The code, which was dependent on the concrete class Ferrari, now only depends on the base class Car. You can easily inject any other car like VW or Fiat into your class. There is no need to search for all “new Ferrari()” commands in your code in case you need to change the type of car. It is all in one place. The dependency on the concrete class is gone.

We can increase the flexibility even further and use:

public interface ICarFactory {
  Car GetObject(string xType);    
} // interface

public class CarFactory : ICarFactory {
  public Car GetObject(string xType) {
    switch (xType) {
      case "Expensive": return new Ferrari();
      case "Average": return new VW();
      case "Cheap": return new Fiat();
      default: return null;
    }
  }
} // class

...
IndependentClass i = new IndependentClass(lCarFactory.GetObject("Expensive"));
...

The string can be replaced by an enum.

public enum eCar { Expensive, Average, Cheap };

public interface ICarFactory {
  Car GetObject(eCar xType);
} // interface

public class CarFactory : ICarFactory {
  public Car GetObject(eCar xType) {
    switch (xType) {
      case eCar.Expensive: return new Ferrari();
      case eCar.Average: return new VW();
      case eCar.Cheap: return new Fiat();
      default: return null;
    }
  } //
} // class

public class IndependentClass1 {
  public readonly Car car;
  public IndependentClass1(Car xCar) {
    car = xCar;
  } // constructor
} // class

public class IndependentClass2 {
  public readonly Car car;
  public IndependentClass2() {
    CarFactory lCarFactory = new CarFactory();
    car = lCarFactory.GetObject(eCar.Expensive);
  } // constructor
} // class

...
class Program {
  static void Main(string[] args) {
    DependentClass d = new DependentClass();
    CarFactory lCarFactory = new CarFactory();
    IndependentClass1 i1 = new IndependentClass1(lCarFactory.GetObject(eCar.Expensive));
    IndependentClass2 i2 = new IndependentClass2();
    Console.WriteLine(i2.car.Name); // Red Speeder
    Console.ReadLine();
  } // main
} // class

The Factory Pattern should only be used, when the need for it becomes great enough. Let’s say you are doing unit testing and you need to spoof the creator of an object. A Factory can be quite helpful then.
Factories add complexity to your code, so do not use them by default. They are conforming with Dependency Injection. Nevertheless, check the price you are willing to pay for independence.

Summary:

  • A factory method returns one of several possible classes that share an interface/abstract class/(parent class).
  • The class is chosen at runtime.
  • Before: Car c = new Ferrari(); After: Car c = lCarFactory.GetObject(eCar.Expensive);
  • Don’t use the Factory Pattern by default.

Cascade pattern / Method chaining

Cascade

Today, I am going to explain a simple programming pattern step by step.
Often the cascade pattern can be found in connection with consecutive data manipulation. It has many names. In C# I would put it in the same chapter as Extension Methods.

But let us start at the very beginning. Genesis 🙂

This is a simple integer calculation.

int r0 = 5;
r0 = ((((r0 + 2) * 4) - 8) / 2) + 1;
Console.WriteLine("Result is " + r0);  // 11

We could break it down into many separate calculation steps …

int r1 = 5;
r1 += 2; r1 *= 4; r1 -= 8; r1 /= 2; r1 += 1;
Console.WriteLine("Result is " + r1);  // 11

… and build a class to perform reoccurring calculations.

public class Classic {
  static public int add(int a, int b) { return a + b; }
  static public int sub(int a, int b) { return a - b; }
  static public int mul(int a, int b) { return a * b; }
  static public int div(int a, int b) { return a / b; }
} // class

int r2 = 5;
r2 = Classic.add(r2, 2);
r2 = Classic.mul(r2, 4);
r2 = Classic.sub(r2, 8);
r2 = Classic.div(r2, 2);
r2 = Classic.add(r2, 1);
Console.WriteLine("Result is " + r2);  // 11

Well, this is nice. But the code is clumsy. We could overload operators. Anyhow, this is not the way I would like to go today. What about a memory variable in form of a property called “Result”.

public class Cascade1 {
  public int Result { get; private set; }

  public Cascade1(int x) { Result = x; }
  public Cascade1 add(int x) { Result += x; return this; }
  public Cascade1 sub(int x) { Result -= x; return this; }
  public Cascade1 mul(int x) { Result *= x; return this; }
  public Cascade1 div(int x) { Result /= x; return this; }
} // class

int c1 = new Cascade1(5)
    .add(2)
    .mul(4)
    .sub(8)
    .div(2)
    .add(1)
    .Result;

Console.WriteLine("Result is " + c1);  // 11

This looks much better, doesn’t it?
We replace the integers by a simple class, which only has one public field called “Age”.

public class Data {
  public int Age;
} // class

We add IENumberable as parameter. Now, the program looks neat and more flexible.

public class Cascade2 {
 public static void add(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age += xValue; }
 public static void sub(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age -= xValue; }
 public static void mul(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age *= xValue; }
 public static void div(IEnumerable<Data> xIENumberable, int xValue) { foreach (Data x in xIENumberable) x.Age /= xValue; }
} // class

List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i });

Cascade2.add(lList, 2);
Cascade2.mul(lList, 4);
Cascade2.sub(lList, 8);
Cascade2.div(lList, 2);
Cascade2.add(lList, 1);

Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " "));

But once again we face too many parameters. Should we add a memory field? No, C# offers Extension Methods. This is the way to go!

public static class Cascade3 {
  public static IEnumerable<Data> add(this IEnumerable<Data> xIENumberable, int xValue) {
    foreach (Data x in xIENumberable) x.Age += xValue;
    return xIENumberable;
  } //

  public static IEnumerable<Data> sub(this IEnumerable<Data> xIENumberable, int xValue) {
    foreach (Data x in xIENumberable) x.Age -= xValue;
    return xIENumberable;
  } // 

  public static IEnumerable<Data> mul(this IEnumerable<Data> xIENumberable, int xValue) {
    foreach (Data x in xIENumberable) x.Age *= xValue;
    return xIENumberable;
  } //

  public static IEnumerable<Data> div(this IEnumerable<Data> xIENumberable, int xValue) {
    foreach (Data x in xIENumberable) x.Age /= xValue;
    return xIENumberable;
  } //
} // class

List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i });
lList.add(2)
  .mul(4)
  .sub(8)
  .div(2)
  .add(1);

Console.Write("Array result is "); lList.ForEach(x => Console.Write(x.Age + " "));

Each List object can now use the extension methods. In C# you most likely have come across such pattern when using the namespace System.Linq. Adding this namespace automatically enables many methods for lists (IENumerable) and arrays. Here is an example of that namespace. You can chain together methods. Make sure the return parameter points to the same list each time, otherwise the chain is broken. For instance a Sum() would return a number rather an IENumerable, thus breaking the chain.

List<Data> lList = new List<Data>(); for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i });

// using System.Linq;
List<Data> lResult = lList.Where(x => x.Age % 2 == 0).Take(10).ToList();
Console.Write("Array result is "); lResult.ForEach(x => Console.Write(x.Age + " "));

Wiki

And here is the entire source code in one piece.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CascadePattern {
  public class Data {
    public int Age;
  } // class

  public static class Cascade3 {
    public static IEnumerable<Data> add(this IEnumerable<Data> xIENumberable, int xValue) {
      foreach (Data x in xIENumberable) x.Age += xValue;
      return xIENumberable;
    } //
    public static IEnumerable<Data> sub(this IEnumerable<Data> xIENumberable, int xValue) {
      foreach (Data x in xIENumberable) x.Age -= xValue;
      return xIENumberable;
    } // 
    public static IEnumerable<Data> mul(this IEnumerable<Data> xIENumberable, int xValue) {
      foreach (Data x in xIENumberable) x.Age *= xValue;
      return xIENumberable;
    } //
    public static IEnumerable<Data> div(this IEnumerable<Data> xIENumberable, int xValue) {
      foreach (Data x in xIENumberable) x.Age /= xValue;
      return xIENumberable;
    } //
  } // class

  class Program {

    public class Classic {
      static public int add(int a, int b) { return a + b; }
      static public int sub(int a, int b) { return a - b; }
      static public int mul(int a, int b) { return a * b; }
      static public int div(int a, int b) { return a / b; }
    } // class

    public class Cascade1 {
      public int Result { get; private set; }

      public Cascade1(int x) { Result = x; }
      public Cascade1 add(int x) { Result += x; return this; }
      public Cascade1 sub(int x) { Result -= x; return this; }
      public Cascade1 mul(int x) { Result *= x; return this; }
      public Cascade1 div(int x) { Result /= x; return this; }

    } // class

    public class Cascade2 {
      public static void add(IEnumerable<Data> xIENumberable, int xValue) {
        foreach (Data x in xIENumberable) x.Age += xValue;
      } //
      public static void sub(IEnumerable<Data> xIENumberable, int xValue) {
        foreach (Data x in xIENumberable) x.Age -= xValue;
      } // 
      public static void mul(IEnumerable<Data> xIENumberable, int xValue) {
        foreach (Data x in xIENumberable) x.Age *= xValue;
      } //
      public static void div(IEnumerable<Data> xIENumberable, int xValue) {
        foreach (Data x in xIENumberable) x.Age /= xValue;
      } //
    } // class


    static void Main(string[] args) {

      int r0 = 5;
      r0 = ((((r0 + 2) * 4) - 8) / 2) + 1;
      Console.WriteLine("Result is " + r0);  // 11

      int r1 = 5;
      r1 += 2; r1 *= 4; r1 -= 8; r1 /= 2; r1 += 1;
      Console.WriteLine("Result is " + r1);  // 11

      int r2 = 5;
      r2 = Classic.add(r2, 2);
      r2 = Classic.mul(r2, 4);
      r2 = Classic.sub(r2, 8);
      r2 = Classic.div(r2, 2);
      r2 = Classic.add(r2, 1);
      Console.WriteLine("Result is " + r2);  // 11

      int c1 = new Cascade1(5)
      .add(2)
      .mul(4)
      .sub(8)
      .div(2)
      .add(1)
      .Result;

      Console.WriteLine("Result is " + c1);  // 11

      List<Data> lList = new List<Data>();
      for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i });

      Cascade2.add(lList, 2);
      Cascade2.mul(lList, 4);
      Cascade2.sub(lList, 8);
      Cascade2.div(lList, 2);
      Cascade2.add(lList, 1);

      Console.Write("Array result is ");
      lList.ForEach(x => Console.Write(x.Age + " "));
      Console.WriteLine();

      lList.Clear();
      for (int i = 0; i < 10; i++) lList.Add(new Data() { Age = i });
      lList.add(2)
      .mul(4)
      .sub(8)
      .div(2)
      .add(1);

      Console.Write("Array result is ");
      lList.ForEach(x => Console.Write(x.Age + " "));
      Console.WriteLine();

      // using System.Linq;
      lList.Clear();
      for (int i = 0; i < 50; i++) lList.Add(new Data() { Age = i });
      List<Data> lResult = lList.Where(x => x.Age % 2 == 0).Take(10).ToList();
      Console.Write("Array result is ");
      lResult.ForEach(x => Console.Write(x.Age + " "));
      Console.ReadLine();

    } //

  } // class
} // namespace

example output:
Result is 11
Result is 11
Result is 11
Result is 11
Array result is 1 3 5 7 9 11 13 15 17 19
Array result is 1 3 5 7 9 11 13 15 17 19
Array result is 0 2 4 6 8 10 12 14 16 18

Routed Events (part 1)

BubblingEvents

Events notify your code that something has happened. You subscribe to events like you subscribe eg. to a monthly magazine. Let’s say a new magazine comes out. The postal worker delivers it to your mail box. You don’t need to ask for the new magazine to be sent to you each time.
Something similar takes place in WPF. A button is pressed and the program delivers that information to your mail box, which is a callback method.

Links:
Events Part1
Events Part2
Events Part3
 

The classical event has a standard pattern:

public delegate void dMyDelegate();
public event dMyDelegate MyEvent;

public void addEvent() { MyEvent += Callback; }
public void removeEvent() { MyEvent -= Callback; }

public void CallEvent() {
  dMyDelegate d = MyEvent;
  if (d == null) return;
  d();
} //

void Callback() { Console.WriteLine("Event raised"); }

Or this:

private EventHandler _Handler;
public event EventHandler MyEvent {
  add { _Handler += value; }
  remove { _Handler -= value; }
} //

...

 
 

But what exactly is a “Routed Event”?

Routed Events are used in connection with WPF. They are required for a certain routing concept. In WinForms the callback is sent by the corresponding component (eg. the button). But in WPF event routing allows an event to take place in one element, but be raised by another one. That way you can handle events in the most convenient place.
A Button could be part of a template, which in turn is a part of a ListView. The Button could have an image, an ornated border, a grid and many extras. It does make sense to receive events on the group level sometimes.

We know direct events from WinForms. A mouse click raises an event. But in WPF there are two more types:

  1. Bubbling Events: They travel up the hierarchy of the visual tree. The click raises an event on the button, then on the grid, then on the window. It also raises events on all objects on the way.
  2. Tunneling Events: These events travel to the opposite direction. A keyboard entry would start at the window level, then travel through the grid towards the button.

 

Let’s just delve into a practical example. Run the code and observe what is happening.

RoutedEvents
 

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="500" Width="630"
        MouseUp="MyMouseUp" PreviewMouseUp="MyPreviewMouseUp">
    <Grid MouseUp="MyMouseUp" PreviewMouseUp="MyPreviewMouseUp">
        <Grid.RowDefinitions>
            <RowDefinition Height="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ListView Name="MyListView" Margin="0,0,0,0" Grid.IsSharedSizeScope="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" MouseUp="MyMouseUp"  PreviewMouseUp="MyPreviewMouseUp" Grid.Row="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <GroupBox Header="Item" FontSize="10">
                        <Grid PreviewMouseUp="MyPreviewMouseUp" MouseUp="MyMouseUp">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition />
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="Name:  " Grid.Column="0" VerticalAlignment="Center"  FontSize="16" PreviewMouseUp="MyPreviewMouseUp"/>
                            <TextBlock Text="{Binding Name}" FontWeight="Bold" Grid.Column="1"  VerticalAlignment="Center" FontSize="16"/>
                            <TextBlock Text="LastName:  " Grid.Column="2"  VerticalAlignment="Center" FontSize="16"/>
                            <TextBlock Text="{Binding LastName}" FontWeight="Bold" Grid.Column="3" VerticalAlignment="Center" FontSize="16"/>
                            <TextBlock Text="Click me" Grid.Column="4" FontSize="16" MouseUp="MyMouseUp" Background="AliceBlue"/>
                        </Grid>
                    </GroupBox>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <TextBox Name="Results" IsReadOnly="True" FontSize="14" ScrollViewer.VerticalScrollBarVisibility="Auto" Height="Auto" Grid.Row="1" />
    </Grid>
</Window>
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;

namespace DemoApp {
  public partial class MainWindow : Window {

    public class Data {
      public string Name { get; set; }
      public string LastName { get; set; }
    } //

    public MainWindow() {
      InitializeComponent();

      List<Data> lItems = new List<Data>() {
        new Data() {Name = "Otto", LastName = "Waalkes"},
        new Data() {Name = "Heinz", LastName = "Rühmann"},
        new Data() {Name = "Michael", LastName = "Herbig"},
        new Data() {Name = "Sky", LastName = "du Mont"},
        new Data() {Name = "Dieter", LastName = "Hallervorden"},
        new Data() {Name = "Diether", LastName = "Krebs"},
        new Data() {Name = "Helga", LastName = "Feddersen"},
        new Data() {Name = "Herbert", LastName = "Grönemeyer"},
      };
      MyListView.ItemsSource = lItems;
    } //

    // bubbling
    private void MyMouseUp(object sender, MouseButtonEventArgs e) {
      FrameworkElement lElement = sender as FrameworkElement;
      string lAppend = Environment.NewLine;
      if (sender is Window) lAppend += Environment.NewLine;
      Results.Text += e.RoutedEvent.RoutingStrategy.ToString() + ": " + lElement.ToString() + lAppend;
      e.Handled = false;
      Results.ScrollToEnd();
    } //

    // tunneling
    private void MyPreviewMouseUp(object sender, MouseButtonEventArgs e) {
      FrameworkElement lElement = sender as FrameworkElement;
      string lAppend = Environment.NewLine;
      if (sender.Equals(e.OriginalSource)) lAppend += Environment.NewLine;
      Results.Text += e.RoutedEvent.RoutingStrategy.ToString() + ": " + lElement.ToString() + lAppend;
      e.Handled = false;
      Results.ScrollToEnd();
    } //

  } // class
} // namespace

 
Tunneling Events are raised before Bubbling Events. The convention for Tunneling Events in .Net is that names have to start with the prefix “Preview”. Therefore The “MouseUp” event is a Bubbling Event and “PreviewMouseUp” is a Tunneling Event.
Today’s XAML source code subscribes to bubbling/tunneling events at several places. Compare the output with the code. In theory you could deal with all events on the window level. Use the e.OriginalSource field of the event argument MouseButtonEventArgs e to distinguish between the many possible events. You will also receive events that you did not explicitly subscribe to. Click into the lower textbox or on a scroll bar; this will raise events on the Grid, (ListView) and Window.

Now, let’s add a tunneling event to the “Click me” TextBlock.

<TextBlock Text="Click me" Grid.Column="4" FontSize="16" MouseUp="MyMouseUp" PreviewMouseUp="MyPreviewMouseUp" Background="AliceBlue"/>

 
This activates the code that was redundant so far:

if (sender.Equals(e.OriginalSource)) lAppend += Environment.NewLine;

 
 
Custom Routed Events

How can we add a custom routed event? Just follow this pattern:

  • Inherit an element from another class.
  • Define a public static readonly RoutedEvent.
  • Register that Event by using the EventManager.
  • Add an “old school” C# event that forwards “old school” subscriptions to your WPF routed event.

 
And here we go. Let’s add a button with a triple click event.

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;

namespace DemoApp {
  public class TripleClickButton : Button {

    /*
     * The methods AddHandler, RemoveHandler and RaiseEvent are inherited from UIElement
     */

    // public static readonly !
    public static readonly RoutedEvent TripleClickEvent = EventManager.RegisterRoutedEvent("TripleClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(TripleClickButton));

    // Link classical approach to the above WPF RoutedEvent.
    // Do not add any complex code here!
    public event RoutedEventHandler TripleClick {
      add { AddHandler(TripleClickEvent, value); }
      remove { RemoveHandler(TripleClickEvent, value); }
    } //

    // How to trigger our Routed Event. 
    void RaiseTripleClickEvent() {
      RoutedEventArgs lRoutedEventArgs = new RoutedEventArgs(TripleClickButton.TripleClickEvent);
      RaiseEvent(lRoutedEventArgs);
    } //

    private List<DateTime> _Clicks = new List<DateTime>();
    protected override void OnClick() {
      lock (_Clicks) { // In theory we do not need a lock, because the event is always raised on the Dispatcher thread.
        DateTime lNow = DateTime.Now;
        _Clicks.Add(lNow);
        if (_Clicks.Count < 3) return;
        if (lNow.Subtract(_Clicks[0]).TotalMilliseconds < 1000) {
          _Clicks.Clear();
          RaiseTripleClickEvent();
          return;
        }
        _Clicks.RemoveAt(0);
      }      
    } //

  } // class
} // namespace

 
Declare the new class in the XAML window namespace and replace the rightmost TextBlock by our new custom button.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:app="clr-namespace:DemoApp"
        ...
       <TextBlock Text="{Binding LastName}" FontWeight="Bold" Grid.Column="3" VerticalAlignment="Center" FontSize="16"/>
       <app:TripleClickButton Content="TripleClick me" Grid.Column="4" FontSize="16" Background="Salmon" TripleClick="TripleClickButton_TripleClick" Tag="{Binding Name}" />
     </Grid>
     ...

 

Define the event itself in the main window. Here is the full code:

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;

namespace DemoApp {
  public partial class MainWindow : Window {

    public class Data {
      public string Name { get; set; }
      public string LastName { get; set; }
    } //

    public MainWindow() {
      InitializeComponent();

      List<Data> lItems = new List<Data>() {
        new Data() {Name = "Otto", LastName = "Waalkes"},
        new Data() {Name = "Heinz", LastName = "Rühmann"},
        new Data() {Name = "Michael", LastName = "Herbig"},
        new Data() {Name = "Sky", LastName = "du Mont"},
        new Data() {Name = "Dieter", LastName = "Hallervorden"},
        new Data() {Name = "Diether", LastName = "Krebs"},
        new Data() {Name = "Helga", LastName = "Feddersen"},
        new Data() {Name = "Herbert", LastName = "Grönemeyer"},
      };
      MyListView.ItemsSource = lItems;

      
    } //

    // bubbling
    private void MyMouseUp(object sender, MouseButtonEventArgs e) {
      FrameworkElement lElement = sender as FrameworkElement;
      string lAppend = Environment.NewLine;
      if (sender is Window) lAppend += Environment.NewLine;
      Results.Text += e.RoutedEvent.RoutingStrategy.ToString() + ": " + lElement.ToString() + lAppend;
      e.Handled = false;
      Results.ScrollToEnd();
    } //

    // tunneling
    private void MyPreviewMouseUp(object sender, MouseButtonEventArgs e) {
      FrameworkElement lElement = sender as FrameworkElement;
      string lAppend = Environment.NewLine;
      if (sender.Equals(e.OriginalSource)) lAppend += Environment.NewLine;
      Results.Text += e.RoutedEvent.RoutingStrategy.ToString() + ": " + lElement.ToString() + lAppend;
      e.Handled = false;
      Results.ScrollToEnd();
    }

    // custom event
    private void TripleClickButton_TripleClick(object sender, RoutedEventArgs e) {
      Button lButton = e.OriginalSource as Button;
      if (lButton == null) return;
      
      Results.Text = "TripleClick received from " + lButton.Tag;
    } //

  } // class
} // namespace

 

And the full XAML:

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:app="clr-namespace:DemoApp"
        Title="MainWindow" Height="500" Width="630"
        MouseUp="MyMouseUp" PreviewMouseUp="MyPreviewMouseUp">
    <Grid MouseUp="MyMouseUp" PreviewMouseUp="MyPreviewMouseUp">
        <Grid.RowDefinitions>
            <RowDefinition Height="300" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <ListView Name="MyListView" Margin="0,0,0,0" Grid.IsSharedSizeScope="True" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.CanContentScroll="True" MouseUp="MyMouseUp"  PreviewMouseUp="MyPreviewMouseUp" Grid.Row="0">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <GroupBox Header="Item" FontSize="10">
                        <Grid PreviewMouseUp="MyPreviewMouseUp" MouseUp="MyMouseUp">
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition />
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition />
                                <ColumnDefinition SharedSizeGroup="A" />
                                <ColumnDefinition />
                            </Grid.ColumnDefinitions>
                            <TextBlock Text="Name:  " Grid.Column="0" VerticalAlignment="Center"  FontSize="16" PreviewMouseUp="MyPreviewMouseUp"/>
                            <TextBlock Text="{Binding Name}" FontWeight="Bold" Grid.Column="1"  VerticalAlignment="Center" FontSize="16"/>
                            <TextBlock Text="LastName:  " Grid.Column="2"  VerticalAlignment="Center" FontSize="16"/>
                            <TextBlock Text="{Binding LastName}" FontWeight="Bold" Grid.Column="3" VerticalAlignment="Center" FontSize="16"/>
                            <app:TripleClickButton Content="TripleClick me" Grid.Column="4" FontSize="16" Background="Salmon" TripleClick="TripleClickButton_TripleClick" Tag="{Binding Name}" />
                        </Grid>
                    </GroupBox>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <TextBox Name="Results" IsReadOnly="True" FontSize="14" ScrollViewer.VerticalScrollBarVisibility="Auto" Height="Auto" Grid.Row="1" />
    </Grid>
</Window>

 

TripleClick

 

The next post will be about:

  • Marking Routed Events as handled to avoid further processing.
  • Suppressing the suppression of the Handled flag.
  • Attached Events
  • Style EventSetters

Stay tuned 😉

WPF Datagrid formatting (part 1)

WpfDataGrid1

This source code demonstrates the use of a simple DataGrid. You can sort the rows by any column. The Age column is horizontally aligned to the right. The column headers are using a bold font.

The DataGrid element itself is very flexible. You can add all kinds of columns. The most interesting one is DataGridTemplateColumn, which allows you to add any template. The example template only uses a DatePicker, but you could add far more complexity to it.

Set the SortMemberPath to enable sorting, otherwise the DataGrid sorting algorithm cannot know what data to look at. Remember, we are using a template and not a clearly identifiable data type. In today’s example SortMemberPath is set to “Birthday.Day”, which sorts by the day of the month. In case you prefer to sort by date in general, use SortMemberPath=”Birthday” instead.

I changed the selection color, because the dark blue had a low contrast compared to the web-links. This is dealt with by style triggers. The advantage of triggers is that they only override properties temporarily. As soon as the trigger becomes invalid the control element returns to its previous formatting.

<Window x:Class="WpfDatagrid.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Language="en-GB"
        Loaded="Window_Loaded"
        Closed="Window_Closed"
        Title="MainWindow" Height="350" Width="525">

    <Window.Resources>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Setter Property="VerticalContentAlignment" Value="Center" />
            <Setter Property="SeparatorBrush" Value="WhiteSmoke" />
            <Setter Property="FontWeight" Value="Bold" />
            <Setter Property="Height" Value="30" />
        </Style>
        <Style x:Key="AlignRight" TargetType="{x:Type TextBlock}">
            <Setter Property="HorizontalAlignment" Value="Right" />
        </Style>
    </Window.Resources>

    <Grid>
        <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding}" CanUserAddRows="False" CanUserReorderColumns="True" CanUserResizeColumns="True" CanUserResizeRows="False" SelectionUnit="Cell" SelectionMode="Extended">
            <DataGrid.CellStyle>
                <Style>
                    <Style.Triggers>
                        <Trigger Property="DataGridCell.IsSelected" Value="True">
                            <Setter Property="DataGridCell.Background" Value="SteelBlue" />
                            <Setter Property="DataGridCell.BorderBrush" Value="GreenYellow" />
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </DataGrid.CellStyle>

            <DataGrid.Columns>
                <DataGridCheckBoxColumn Header="Alive" Binding="{Binding Alive}" />
                <DataGridTextColumn Header="Name" Binding="{Binding FirstName}" />
                <DataGridTextColumn Header="LastName" Binding="{Binding LastName}" />

                <!--<DataGridTemplateColumn Header="Birthday" SortMemberPath="Birthday">-->
                <DataGridTemplateColumn Header="Birthday" SortMemberPath="Birthday.Day">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DatePicker SelectedDate="{Binding Birthday}" BorderThickness="0" />
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>

                <DataGridTextColumn Header="Age" Binding="{Binding Age, StringFormat=N2}" ElementStyle="{StaticResource AlignRight}" IsReadOnly="True" />

                <DataGridHyperlinkColumn Header="Homepage" Binding="{Binding Homepage}" IsReadOnly="True">
                    <DataGridHyperlinkColumn.ElementStyle>
                        <Style>
                            <EventSetter Event="Hyperlink.Click" Handler="Hyperlink_Clicked"/>
                        </Style>
                    </DataGridHyperlinkColumn.ElementStyle>
                </DataGridHyperlinkColumn>



            </DataGrid.Columns>
        </DataGrid>
    </Grid>

</Window>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Windows;
using System.Windows.Documents;

namespace WpfDatagrid {

  public partial class MainWindow : Window {

    public class Person {
      public bool Alive { get; set; }
      public string FirstName { get; set; }
      public string LastName { get; set; }
      public DateTime Birthday { get; set; }
      public double Age { get { return DateTime.Now.Subtract(Birthday).TotalDays / 365; } }
      public string Homepage { get; set; }
    } //

    public MainWindow() {
      InitializeComponent();
    } //

    private void Window_Loaded(object sender, RoutedEventArgs e) {
      List<Person> lPersons = new List<Person>();
      lPersons.Add(new Person() { FirstName = "Liza", LastName = "Minnelli", Birthday = new DateTime(1946, 03, 12), Alive = true, Homepage = "www.officiallizaminnelli.com" });
      lPersons.Add(new Person() { FirstName = "Bastian", LastName = "Ohta", Birthday = new DateTime(1975, 03, 13), Alive = true, Homepage = "www.ohta.de" });
      lPersons.Add(new Person() { FirstName = "Albert", LastName = "Einstein", Birthday = new DateTime(1879, 03, 14), Alive = false, Homepage = "www.alberteinsteinsite.com" });
      lPersons.Add(new Person() { FirstName = "Coenraad", LastName = "van Houten", Birthday = new DateTime(1801, 03, 15), Alive = false, Homepage = "www.vanhoutendrinks.com" });
      lPersons.Add(new Person() { FirstName = "Andrew", LastName = "Miller-Jones", Birthday = new DateTime(1910, 03, 16), Alive = false, Homepage = "dead as a Dodo" });
      lPersons.Add(new Person() { FirstName = "Gottlieb", LastName = "Daimler", Birthday = new DateTime(1834, 03, 17), Alive = false, Homepage = "www.daimler.com" });
      lPersons.Add(new Person() { FirstName = "Rudolf", LastName = "Diesel", Birthday = new DateTime(1858, 03, 18), Alive = false, Homepage = "http://en.wikipedia.org/wiki/Rudolf_Diesel" });
      DataContext = lPersons;
    } //

    private void Window_Closed(object sender, EventArgs e) {
      Application.Current.Shutdown(0);      
    } //

    private void Hyperlink_Clicked(object sender, RoutedEventArgs e) {
      try {
        Hyperlink lHyperlink = e.OriginalSource as Hyperlink;
        string lUri = lHyperlink.NavigateUri.OriginalString;
        Process.Start(lUri);
      }
      catch (Exception ex) { MessageBox.Show(ex.Message); }
    } //

  } // class
} // namespace

WPF Commands (part 2)

Let’s start with a program that uses Cut, Copy and Paste in two TextBoxes without writing any C# code. This is not a typo. We only need XAML for this.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="400">    
    <DockPanel LastChildFill="True" >
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_Edit">
                <MenuItem Command="{x:Static ApplicationCommands.Cut}" CommandParameter="Cut it!"/>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" CommandParameter="Copy it!"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" CommandParameter="Paste it!"/>
            </MenuItem>
        </Menu>     

        <ToolBarTray Background="Gray" DockPanel.Dock="Top">
            <ToolBar Band="0" BandIndex="0" >
                <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
                <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
                <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            </ToolBar>
            <ToolBar Band="1" BandIndex="1">
                <ToolBarPanel Orientation="Vertical">
                    <Label Content="Dummy0" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy1" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy2" ToolBar.OverflowMode="AsNeeded" />
                </ToolBarPanel>
            </ToolBar>
        </ToolBarTray>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="0" Grid.ColumnSpan="1" Margin="0" >It happened that a Fox caught its tail in a trap, and in struggling to release himself lost all of it but the stump. At first he was ashamed to show himself among his fellow foxes.</TextBox>
            <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,0,0,0" Width="3"/>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="2" Grid.ColumnSpan="1" Margin="0" >But at last he determined to put a bolder face upon his misfortune, and summoned all the foxes to a general meeting to consider a proposal which he had to place before them.</TextBox>
        </Grid>
    </DockPanel>
</Window>

Editor

 

I added a Toolbar with some dummy labels just to keep the learning curve going. You remove them without any risk.

What is happening here?

Some input controls handle command events on their own. Everything is built-in already. All you need to do is to provide the Buttons or MenuItems which call these commands. The elements even enable/disable themselves. We have two textboxes in the example. These commands are applied to the element that has the focus.
How can this be achieved? The element finds the window instance and then determines what element was focused previously. This only works for Toolbars and Menus UNLESS you set the CommandTarget property  manually.

Let’s add standard buttons now. You cannot see any effect when you press them. The buttons are even ghosted. To solve this we assign the names TextBox1 and TextBox2 and link the Button CommandTargets to these elements.

 

NotWorking

 

You can now cut or copy from TextBox1 and paste it into TextBox2.
 

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="400">    
    <DockPanel LastChildFill="True" >
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_Edit">
                <MenuItem Command="{x:Static ApplicationCommands.Cut}" CommandParameter="Cut"/>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" CommandParameter="Copy"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" CommandParameter="Paste"/>
            </MenuItem>
        </Menu>     

        <ToolBarTray Background="Gray" DockPanel.Dock="Top">
            <ToolBar Band="0" BandIndex="0" >
                <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
                <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
                <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            </ToolBar>
            <ToolBar Band="1" BandIndex="1">
                <ToolBarPanel Orientation="Vertical">
                    <Label Content="Dummy0" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy1" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy2" ToolBar.OverflowMode="AsNeeded" />
                </ToolBarPanel>
            </ToolBar>
        </ToolBarTray>
<!-- changed -->
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
            <Button Command="{x:Static ApplicationCommands.Cut}" CommandTarget="{Binding ElementName=TextBox1}" Content="Cut" />
            <Button Command="{x:Static ApplicationCommands.Copy}" CommandTarget="{Binding ElementName=TextBox1}" Content="Copy" />
            <Button Command="{x:Static ApplicationCommands.Paste}" CommandTarget="{Binding ElementName=TextBox2}"  Content="Paste" />
        </StackPanel>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
<!-- changed -->
            <TextBox Name="TextBox1" TextWrapping="Wrap" Width="Auto" Grid.Column="0" Grid.ColumnSpan="1" Margin="0" >It happened that a Fox caught its tail in a trap, and in struggling to release himself lost all of it but the stump. At first he was ashamed to show himself among his fellow foxes.</TextBox>
            <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,0,0,0" Width="3"/>
<!-- changed -->
            <TextBox Name="TextBox2" TextWrapping="Wrap" Width="Auto" Grid.Column="2" Grid.ColumnSpan="1" Margin="0" >But at last he determined to put a bolder face upon his misfortune, and summoned all the foxes to a general meeting to consider a proposal which he had to place before them.</TextBox>
        </Grid>

    </DockPanel>
</Window>

But hardcoding is a really bad approach. Therefore we are going to use FocusManager.IsFocusScope=”True” instead. WPF then checks the parent focus. By default, the Window class is a focus scope as are the Menu, ContextMenu, and ToolBar classes.
The following example is flawless.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="400">    
    <DockPanel LastChildFill="True" >
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_Edit">
                <MenuItem Command="{x:Static ApplicationCommands.Cut}" CommandParameter="Cut"/>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" CommandParameter="Copy"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" CommandParameter="Paste"/>
            </MenuItem>
        </Menu>     

        <ToolBarTray Background="Gray" DockPanel.Dock="Top">
            <ToolBar Band="0" BandIndex="0" >
                <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
                <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
                <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            </ToolBar>
            <ToolBar Band="1" BandIndex="1">
                <ToolBarPanel Orientation="Vertical">
                    <Label Content="Dummy0" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy1" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy2" ToolBar.OverflowMode="AsNeeded" />
                </ToolBarPanel>
            </ToolBar>
        </ToolBarTray>
<!-- changed -->
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" FocusManager.IsFocusScope="True">
            <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
            <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
            <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
        </StackPanel>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="0" Grid.ColumnSpan="1" Margin="0" >It happened that a Fox caught its tail in a trap, and in struggling to release himself lost all of it but the stump. At first he was ashamed to show himself among his fellow foxes.</TextBox>
            <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,0,0,0" Width="3"/>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="2" Grid.ColumnSpan="1" Margin="0" >But at last he determined to put a bolder face upon his misfortune, and summoned all the foxes to a general meeting to consider a proposal which he had to place before them.</TextBox>
        </Grid>

    </DockPanel>
</Window>

The IsFocusScope approach has the advantage that the same commands apply to several controls.

 
 
Custom Commands
 

We are going to write our own commands now. For this we need to create a class and add a property that returns a RoutedUICommand instance. This property needs to be static. And to initialize this class you also need a static constructor.

using System.Windows.Input;

namespace CustomCommands {
 
  public class PlaySound {

    static PlaySound() {
      KeyGesture lShortCut = new KeyGesture(Key.P, ModifierKeys.Control, "Ctrl+p");
      InputGestureCollection InputGestureCollection = new InputGestureCollection();
      InputGestureCollection.Add(lShortCut);
      PlaySoundCommand = new RoutedUICommand("Play", "PlaySound", typeof(PlaySound), InputGestureCollection);      
    } // static constructor

    public static RoutedUICommand PlaySoundCommand { get; private set; }
  } // class

} // namespace

The MainWindow class should look like this. The method CommandBinding_PlaySound_Executed plays the system beep sound.

using System.Windows;
using System.Windows.Input;

namespace DemoApp {

  public partial class MainWindow : Window {

    public MainWindow() {
      InitializeComponent();
    }

   private void CommandBinding_PlaySound_Executed(object sender, ExecutedRoutedEventArgs e) {
      System.Media.SystemSounds.Beep.Play();      
      MessageBox.Show("Source: " + e.Source.ToString() + Environment.NewLine + 
        "OriginalSource: " + e.OriginalSource.ToString() + Environment.NewLine + 
        "Parameter: " + e.Parameter.ToString());
    } //

  } // class
} // namespace

Add the class in your XAML namespace. I used xmlns:c=”clr-namespace:CustomCommands” .

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:c="clr-namespace:CustomCommands"
        Title="MainWindow" Height="400" Width="400">
<!-- above was changed -->
    <Window.CommandBindings>
<!-- changed -->
        <CommandBinding Command="c:PlaySound.PlaySoundCommand" Executed="CommandBinding_PlaySound_Executed" />
    </Window.CommandBindings>
    <DockPanel LastChildFill="True" >
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_Edit">
                <MenuItem Command="{x:Static ApplicationCommands.Cut}" CommandParameter="Cut"/>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" CommandParameter="Copy"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" CommandParameter="Paste"/>
            </MenuItem>
            <MenuItem Header="_Media">
                <MenuItem Command="c:PlaySound.PlaySoundCommand" CommandParameter="Play"/>
            </MenuItem>
        </Menu>     

        <ToolBarTray Background="Gray" DockPanel.Dock="Top">
            <ToolBar Band="0" BandIndex="0" >
                <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
                <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
                <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            </ToolBar>
            <ToolBar Band="1" BandIndex="1">
                <ToolBarPanel Orientation="Vertical">
                    <Label Content="Dummy0" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy1" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy2" ToolBar.OverflowMode="AsNeeded" />
                </ToolBarPanel>
            </ToolBar>
        </ToolBarTray>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" FocusManager.IsFocusScope="True">
            <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
            <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
            <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
<!-- changed -->
            <Button Command="c:PlaySound.PlaySoundCommand" Content="Play" CommandParameter="What a lovely song!" />
        </StackPanel>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="0" Grid.ColumnSpan="1" Margin="0" >It happened that a Fox caught its tail in a trap, and in struggling to release himself lost all of it but the stump. At first he was ashamed to show himself among his fellow foxes.</TextBox>
            <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,0,0,0" Width="3"/>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="2" Grid.ColumnSpan="1" Margin="0" >But at last he determined to put a bolder face upon his misfortune, and summoned all the foxes to a general meeting to consider a proposal which he had to place before them.</TextBox>
        </Grid>

    </DockPanel>
</Window>

PlaySound

There is a shortcut to calling commands. You can create an ICommand instance and provide it via a property. The downside – what did you expect? – is that you have no shortcut key or any other comfort.

Step 1: Create a class that inherits from interface ICommand.

using System;
using System.Windows.Input;

namespace CustomCommands {

  public class PlaySound2 : ICommand {
    object _DependencyObject;

    public PlaySound2(object xDependencyObject) {
      _DependencyObject = xDependencyObject;
    } // constructor

    public event EventHandler CanExecuteChanged {
      add { CommandManager.RequerySuggested += value; }
      remove { CommandManager.RequerySuggested -= value; }
    } //

    public bool CanExecute(object xParameter) {
      return (DateTime.Now.Second % 2 == 0); // timer based example
    } //

    public void Execute(object xParameter) {
      //_DependencyObject.DoSomething();
      System.Windows.MessageBox.Show("Parameter: " + xParameter.ToString());
      System.Media.SystemSounds.Beep.Play();
    } //


  } // class
} // namespace

Step 2: instantiate that class and provide it via a property. You do not need to expose the class in your MainWindow. You can use any class. Set the DataContext to your class where the property is (or use a precise path that leads to that object).

using CustomCommands;
using System;
using System.Windows;
using System.Windows.Input;

namespace DemoApp {

  public partial class MainWindow : Window {

    public MainWindow() {
      InitializeComponent();
      SimpleExecution = new PlaySound2("dummy");
      DataContext = this;
    }

    private void CommandBinding_PlaySound_Executed(object sender, ExecutedRoutedEventArgs e) {
      System.Media.SystemSounds.Beep.Play();
      MessageBox.Show("Source: " + e.Source.ToString() + Environment.NewLine +
        "OriginalSource: " + e.OriginalSource.ToString() + Environment.NewLine +
        "Parameter: " + e.Parameter.ToString());
    } //

    public ICommand SimpleExecution { get; private set; }

  } // class
} // namespace

Step 3: Bind the command in XAML.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        
        xmlns:c="clr-namespace:CustomCommands"
        Title="MainWindow" Height="400" Width="400">
    <Window.CommandBindings>
        <CommandBinding Command="c:PlaySound.PlaySoundCommand" Executed="CommandBinding_PlaySound_Executed" />
    </Window.CommandBindings>
    <DockPanel LastChildFill="True" >
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="_Edit">
                <MenuItem Command="{x:Static ApplicationCommands.Cut}" CommandParameter="Cut"/>
                <MenuItem Command="{x:Static ApplicationCommands.Copy}" CommandParameter="Copy"/>
                <MenuItem Command="{x:Static ApplicationCommands.Paste}" CommandParameter="Paste"/>
            </MenuItem>
            <MenuItem Header="_Media">
                <MenuItem Command="c:PlaySound.PlaySoundCommand" CommandParameter="Play"/>
            </MenuItem>
        </Menu>     

        <ToolBarTray Background="Gray" DockPanel.Dock="Top">
            <ToolBar Band="0" BandIndex="0" >
                <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
                <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
                <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            </ToolBar>
            <ToolBar Band="1" BandIndex="1">
                <ToolBarPanel Orientation="Vertical">
                    <Label Content="Dummy0" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy1" ToolBar.OverflowMode="AsNeeded" />
                    <Label Content="Dummy2" ToolBar.OverflowMode="AsNeeded" />
                </ToolBarPanel>
            </ToolBar>
        </ToolBarTray>
        <StackPanel Orientation="Horizontal" DockPanel.Dock="Top" FocusManager.IsFocusScope="True">
            <Button Command="{x:Static ApplicationCommands.Cut}" Content="Cut" />
            <Button Command="{x:Static ApplicationCommands.Copy}" Content="Copy" />
            <Button Command="{x:Static ApplicationCommands.Paste}" Content="Paste" />
            <Button Command="c:PlaySound.PlaySoundCommand" Content="Play" CommandParameter="What a lovely song!" />
<!-- changed -->
            <Button Command="{Binding SimpleExecution}" Content="StraightForward" CommandParameter="The German way!" />
       </StackPanel>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="0" Grid.ColumnSpan="1" Margin="0" >It happened that a Fox caught its tail in a trap, and in struggling to release himself lost all of it but the stump. At first he was ashamed to show himself among his fellow foxes.</TextBox>
            <GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="1,0,0,0" Width="3"/>
            <TextBox TextWrapping="Wrap" Width="Auto" Grid.Column="2" Grid.ColumnSpan="1" Margin="0" >But at last he determined to put a bolder face upon his misfortune, and summoned all the foxes to a general meeting to consider a proposal which he had to place before them.</TextBox>
        </Grid>

    </DockPanel>
</Window>

LastExample

That’s it for today 🙂

WPF Commands (part 1)

Due to personal time limitations I add a shorter post today. Nonetheless this post is vital for programmers without any WPF experience.

Events are fairly low-level and deprecated in WPF to a certain degree. They are against the idea of MVVM, which in simple terms is the separation of code and user interface. The new technology is task based – known as commands. Commands act like glue between the user interface and the code. You can avoid a lot of repetitive event-handling code. They deal with text captions and enabled/disabled state synchronizations. Let’s have a look at the ICommand interface:

namespace System.Windows.Input {

   public interface ICommand {
      event EventHandler CanExecuteChanged;
      bool CanExecute(object parameter);
      void Execute(object parameter);
   } // interface

} // namespace

The interface ICommand is inherited by RoutedCommand and indirectly by RoutedUICommand. RoutedUICommand has an additional descriptive text property, which RoutedCommand does not have. Besides this they are the same. RoutedUICommand inherits from RoutedCommand and is used for commands that display some text in the UI like menu items or tooltips.

namespace System.Windows.Input {

   public class RoutedUICommand : RoutedCommand {
      public RoutedUICommand();
      public RoutedUICommand(string text, string name, Type ownerType);
      public RoutedUICommand(string text, string name, Type ownerType, InputGestureCollection inputGestures);
      public string Text { get; set; }       // Text that describes this command.
   } // class

} // namespace

RoutedCommand is the only class in WPF that inherits from ICommand. All other classes are derived from RoutedCommand. An important feature of RoutedCommand in WPF is the so-called bubbling behavior. When you have a button in a StackPanel, then events will be executed in that order: Button -> StackPanel -> Window. I will keep it simple here and explain that behavior in another posts.

WPF has prebuild commands like Cut, Copy, Paste, Open and Print. There is no code behind these commands. You have to bind them to your code. Bubbling does play a big role here. You could press Ctrl+C to copy a text. The same command could be part of a TextBox and a window menu. The bubbling can be used to place the same command in two different places. The key input triggers the window command and provides enough information to process it.
Prebuild commands define a standard and generally increase code reusability.

Notice that RoutedCommand has its enhanced versions of CanExecute() and Execute():

namespace System.Windows.Input {

   public class RoutedCommand : RoutedCommand {
      public RoutedCommand();
      public RoutedCommand(string name, Type ownerType);
      public RoutedCommand(string name, Type ownerType, InputGestureCollection inputGestures);
      public InputGestureCollection InputGestures { get; }
      public string Name { get; }
      public Type OwnerType { get; }

      public event EventHandler CanExecuteChanged;
      public bool CanExecute(object parameter, IInputElement target);
      public void Execute(object parameter, IInputElement target);
   } // class

} // namespace

This is confusing. You naturally expect the same definition as in ICommand. The answer must be that the interface ICommand is implemented explicitly. Thus the interface method is hidden and can only be accessed indirectly via an interface variable. See below example:

public interface IMyInterface {
    void hello(object o);
} // interface

public class MyClass : IMyInterface {
  public void hello(object i, string s) { }
  void IMyInterface.hello(object o) {}
} // class

static void Main(string[] args) {
  MyClass x = new MyClass();       
  x.hello("abc", "abc");  // interface not accessible
  IMyInterface c = x;
  c.hello("abc");  // class not accessible
}

There are several groups (static classes) of prebuild commands in WPF.
ApplicationCommands provides classical commands that are in most applications (eg. Cut, Copy, Paste, Save, New, Print).
NavigationCommands provide commands for navigation that you know from browsers (eg. BrowseForward, BrowseBack).
EditingCommands are known from text editors (eg. Delete, MoveToDocumentEnd, MoveRightByWord, DecreaseFontSize).
ComponentCommands are used to move the cursor around (some duplicates are in EditingCommands; eg. MoveDown, MoveFocusBack, ExtendSelectionDown).
MediaCommands are self-explanatory (eg. Play, Pause, Record, BoostBass, ChannelDown).

These classes are static, there can only one instance in your application. They all have default keystrokes. For instance Ctrl+C is predefined for Copy. When you bind them to a command source and add that command source to a window, then the key combination becomes active. You don’t even need a visible control. An additional feature is that key combinations of commands are automatically shown in menus.

We had some theory now. Let’s get practical:

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="200">
    <StackPanel>
        <Button Command="{x:Static ApplicationCommands.New}" CommandParameter="NewProjectX" Content="New" FontSize="20" />
    </StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Input;

namespace DemoApp {

  public partial class MainWindow : Window {

    public MainWindow() {
      InitializeComponent();

      CommandBinding lCommandBinding = new CommandBinding(ApplicationCommands.New);
      lCommandBinding.Executed += Button_Pressed;
      CommandBindings.Add(lCommandBinding); // add the binding object to our main "window" instance
    } //

    private void Button_Pressed(object sender, ExecutedRoutedEventArgs e) {
      MessageBox.Show(sender.ToString() + " did send the message: " + e.Parameter.ToString() + Environment.NewLine + "OriginalSource: " + e.OriginalSource);
    } //

  } // class
} // namespace

Window1

Window2

You don’t have to add the command in your C# code. You can add it directly in XAML. This can be more comfortable. Unfortunately there is a downside as well. The IntelliSense support suffers and I personally believe that it is more error-prone.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="200">
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static ApplicationCommands.New}" Executed="Button_Pressed" />
    </Window.CommandBindings>
    <StackPanel>
        <Button Command="{x:Static ApplicationCommands.New}" CommandParameter="NewProjectX" Content="New" FontSize="20" />
    </StackPanel>
</Window>
using System;
using System.Windows;
using System.Windows.Input;

namespace DemoApp {

  public partial class MainWindow : Window {

    public MainWindow() {
      InitializeComponent();

      //CommandBinding lCommandBinding = new CommandBinding(ApplicationCommands.New);
      //lCommandBinding.Executed += Button_Pressed;
      //CommandBindings.Add(lCommandBinding); // add the binding object to the window
    } //

    private void Button_Pressed(object sender, ExecutedRoutedEventArgs e) {
      MessageBox.Show(sender.ToString() + " did send the message: " + e.Parameter.ToString() + Environment.NewLine + "OriginalSource: " + e.OriginalSource);
    } //

  } // class
} // namespace

The next example adds a menu. The shortcut Ctrl+N is automatically shown. There is a slight change for the button as well. The object content (text) now binds to itself and uses the text from the command. The advantage is that you hardcode less and become more flexible on multi-language support later on.
You don’t have to change anything in the C# source code.

<Window x:Class="DemoApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="200" Width="200">
    <Window.CommandBindings>
        <CommandBinding Command="{x:Static ApplicationCommands.New}" Executed="Button_Pressed" />
    </Window.CommandBindings>
    <StackPanel>
        <Menu>
            <MenuItem Header="_File">
                <MenuItem Command="{x:Static ApplicationCommands.New}" CommandParameter="NewProject_Y"/>
            </MenuItem>
        </Menu>
        <Separator/>
        <Button Command="{x:Static ApplicationCommands.New}" CommandParameter="NewProject_X" Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" FontSize="20" />
    </StackPanel>
</Window>

Window3

Window4

Final note: Do not use the old school WinForms like approach anymore:

<Button Click="Button_Click" CommandParameter="NewProject_C" FontSize="20">Click</Button>
private void Button_Click(object sender, RoutedEventArgs e) { MessageBox.Show("Button clicked"); } 

The next post will follow-up on custom commands.