Faking Multiple Inheritance With Event Handlers
December 18th, 2005

I’m going to take a page from the Book of Darrel and post some design patterns whenever I realize that I’m using them. I’d like to be careful because I think that there are a few camps when it comes to design patterns:

  1. Design patterns are very important, very specific, and are a great thing to quiz people about in an interview.
  2. Design patterns are more fluid, something that is figured out when you’re factoring code. There is no way you will not discover these on your own.

I lean to the second category. The quizzers may know little else (you’ll see the same attitude with plenty of other development topics).

Now that you know how to take my writing about design patterns, let’s suppose that you want to make a Windows form that becomes a little translucent when it is inactive. That may or may not be annoying, but there is a very straightforward way to make it happen:


    // Form that becomes transparent when it is inactive
    public class Foo : Form
    {
        private const double c_InactiveOpacity = 0.25d;
        private double _prevOpacity;
    
        protected override void OnDeactivate(EventArgs e)
        {
            _prevOpacity = this.Opacity;
            this.Opacity = c_InactiveOpacity;
            base.OnDeactivate(e);
        }
    
        protected override void OnActivated(EventArgs e)
        {
            this.Opacity = _prevOpacity;
            base.OnActivated(e);
        }
    
        public Foo()
        {
            _prevOpacity = 1.0d;
        }
    }

  

Which works fine, unless you want TWO forms that do that, the second with a special base class not related to the heirarchy of the first.

public class Foo2 : SpecialForm
{
    // criminy
}

This conundrum could be resolved in a few ways:

  1. Ctrl+C, Ctrl+V.
  2. Multiple base classes.
  3. What I am going to call the “Extender Pattern.”

If you picked the first option, I think it’d be better for both of us if you unsubscribed from my feed. The second option would work fine, but CLR languages don’t support it. Some days this bothers me, but most days I think it’s a good thing. Especially when I factor a solution that is just as elegant.

I’m calling that solution the “Extender Pattern” without bothering to find out if anyone has used this term to describe anything else. As I explained above, this is more about artistic sensibility than it is about hard rules and book learning. Not that I’m anti-book learning.

The basic idea is this: you have a set of components that support certain properties, methods, and events. The forms, in this case. You add in to the mix a set of small objects whose only responsibility is to wait for events from the components and make very directed changes to them.

So here is such a class for the problem stated above:


    // Alters the target form's transparency level
    // when it is activated/deactivated.
    public class TransparencyExtender
    {
        private Form _target;
        private double _prevOpacity;
        private const double c_opacity = 0.25d;
    
        public TransparencyExtender(Form target)
        {
            _target = target;
            _prevOpacity = target.Opacity;
            target.Activated +=
                 new EventHandler(Activated);
            target.Deactivate +=
                 new EventHandler(Deactivate);
        }
    
        void Deactivate(object sender, EventArgs e)
        {
            _prevOpacity = _target.Opacity;
            if (_prevOpacity >= c_opacity)
            {
                _target.Opacity = c_opacity;
            }
        }
    
        void Activated(object sender, EventArgs e)
        {
            _target.Opacity = _prevOpacity;
        }
    }

  

Given this, we can write our forms very easily:


    public class Foo : Form
    {
        private TransparencyExtender _tExt =
            new TransparencyExtender(this);
    }
    
    public class Foo2 : SpecialForm
    {
        private TransparencyExtender _tExt =
            new TransparencyExtender(this);
    }

  

Keep in mind that I am not claiming that this is original. It’s really the same as a small secondary base class in C++. However, I think there’s value in looking at the same problem in different ways.

In a real application I’m working on, I’ve written a handful of other window/control styles that can be applied and removed on the fly or from the designer. Again, not original, but I like my little framework. Perhaps I’ll post this someday, or turn it into a product.

I like event/message-driven programming the more I try to use it. I’m using Windows Forms as an example here, but it would be wrong to assume that’s the only place this could be applied. I’ve done the same kinds of things in ASP.NET.