Monthly Archives: June 2014

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

Advertisements

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 2)

BubblingEvents

Referring back to Routed Events (to part 1), let’s have a closer look at this part of the example source code:

// 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();
} //

 

Suppressing Events

e.Handled allows you to halt the event routing process. Set this boolean to true and the event stops traveling any further. A small change demonstrates the altered behavior:

// 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 = (e.ChangedButton == MouseButton.Right);
  Results.ScrollToEnd();
} //

If you use the right MouseButton now, the bubbling routing event process stops. The same applies to the tunneling process when you change the MyPreviewMouseUp() method accordingly.

 


Raising Suppressed Events

You can avoid the suppression of Routed Events. This cannot be done through XAML. Use the AddHandler() method instead. An overload accepts a boolean for its third parameter. Set this one to true and you will receive events even if the e.Handled flag was set to true.

Let’s slightly change our example source code to:

<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"
        Name="MyWindow" PreviewMouseUp="MyPreviewMouseUp">
    ...
...
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;
  MyWindow.AddHandler(UIElement.MouseUpEvent, new MouseButtonEventHandler(MyMouseUp), true);      
} //
...

Et voilà! The Routed Event gets executed despite the set e.Handled flag.

 
Attached Events

The Click event is defined in the ButtonBase class. It is a kind of combination of a Button press and release. But how can you use the bubbling behavior on a higher level like eg. a Grid that does not derive from the ButtonBase class? Attached events enable you to add event handlers to arbitrary elements, which do not define or inherit these.
Let’s add a Click event to the window level by adding Button.Click=”MyClick”:

<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"
        Name="MyWindow" PreviewMouseUp="MyPreviewMouseUp"
        Button.Click="MyClick" >
    ...
private void MyClick(object sender, RoutedEventArgs e) {
  MessageBox.Show("Click received!");
} //

The program does not raise any Click events. We did even override the Click event of our TripleClickButton class. You won’t see a lot. But have a look at the two scroll bars. The scroll bar background (not the scroll bar itself) raises click events. As we are on the window level, we now receive these unexpected events. Indeed, this is a good example. A click of the scroll bar background bubbles through the hierarchy and finally raises the attached Click event on the window level.
Don’t forget to analyse the e.Source of your event parameter. You need to filter out the right Click event.

 

Style EventSetter

While Property setters are most common in Styles, EventSetters are rarely seen. They can be used for more complex problems. The simple ones should be solved by using Style.Triggers. Let’s say you want to change the color of a TextBlock when entering or leaving the area with the mouse cursor.

...
<Window.Resources>
    <Style x:Key="ChangeBackgroundColor" TargetType="TextBlock">
        <EventSetter Event="TextBlock.MouseEnter" Handler="ChangeBackgroundColorOnMouseEnter" /> // direct event
        <EventSetter Event="TextBlock.MouseLeave" Handler="ChangeBackgroundColorOnMouseLeave" /> // direct event
    </Style>
</Window.Resources>
...
<TextBlock Text="LastName:  " Grid.Column="2"  VerticalAlignment="Center" FontSize="16" Style="{StaticResource ChangeBackgroundColor}"/>
...
    private void ChangeBackgroundColorOnMouseEnter(object sender, MouseEventArgs e) { ((TextBlock)sender).Background = Brushes.Red; }
    private void ChangeBackgroundColorOnMouseLeave(object sender, MouseEventArgs e) { ((TextBlock)sender).Background = null; }

 

This example could be simplified. No C# code required:

...
<Window.Resources>
    <Style x:Key="ChangeBackgroundColor" TargetType="TextBlock">
        <Style.Triggers>
            <Trigger Property="TextBlock.IsMouseOver" Value="True">
                <Setter Property="TextBlock.Background" Value="Red" />
            </Trigger>
        </Style.Triggers>                       
    </Style>
</Window.Resources>
...
<TextBlock Text="LastName:  " Grid.Column="2"  VerticalAlignment="Center" FontSize="16" Style="{StaticResource ChangeBackgroundColor}"/>
...

 

I see the need for further explanations on Trigger types. I have just added a reminder on my To-Do-List.
But for now a simple list must suffice:

  • Trigger: Simplest trigger form. Reacts on DependencyProperty changes and then uses setters to change styles.
  • MultiTrigger: Combines multiple Triggers. All conditions must be met.
  • DataTrigger: Reacts on changes in bound data.
  • MultiDataTrigger: Combines multiple DataTriggers. All conditions must be met.
  • EventTrigger: Reacts on events. Used for animations.

In a nutshell: There are three trigger types. They use dependency properties, routed events or data binding.