Silverlight usercontrol inheritance

Demo and source code included below. inheritance-monkies

At some point you think wouldn't it be better to move all this functionality to  a super class ? And right you are. Since we all live in objectville it's not so uncommon. In my case I tried  to move some of the boring position functionality to a base control. We all know that creating a basecontrol is peanuts. But when we do this in a Silverlight control we run in some trouble. Since our control lives in two files defined by two partial classes. Partners in crime are the XAML file and the .cs (aka codebehind) file. So when our .cs file inherits from basecontrol our XAML has to follow. You probably think  so be it, no problem. The problem occurs when you re-open that control in Expression Blend. For no reason whatsoever Expression Blend kicks out the basecontrol. If you don't mind changing the XAML file every time you opened it in blend skip the rest of this post.

Method 1 : Inject your XAML friend into a new control

Create a basecontrol. This sample basecontrol contains some methods and properties to move the control around in a easy way. At line 19 we set the control which is the most important part in this code.

using System.Windows.Controls;

namespace InheritenceSample
{
    public class BaseControl
    {
        private UserControl userControl;

        public UserControl UserControl
        {
            get
            {
                return userControl;
            }
        }

        public BaseControl(UserControl userControl)
        {
            this.userControl = userControl;
        }

        public double Left
        {
            get
            {
                return (double) userControl.GetValue(Canvas.LeftProperty);
            }
            set
            {
                userControl.SetValue(Canvas.LeftProperty, value);
            }
        }

        public double Top
        {
            get
            {
                return (double)userControl.GetValue(Canvas.TopProperty);
            }
            set
            {
                userControl.SetValue(Canvas.TopProperty, value);
            }
        }

        public void MoveTo(double left, double top)
        {
            Left = left;
            Top = top;
        }
    }
}

Create a wrapper control which will contain the XAML control. At line 7 we pass a new instance of our control containing the XAML into the constructor.

namespace InheritenceSample
{
    public class Monkey : BaseControl
    {

        // Set XAML file through the constuctor of the base file.
        public Monkey()
            : base(new MonkeyDesign())
        {
        }

    }
}

That's it. Advantage:

Disadvantage:

Method 2 : Strategy pattern

Our second method makes use of the well known strategy pattern and design pattern rule"Composition over Inheritance". Create an interface which defines the helper class.

using System;
namespace InheritenceSample.Interfaces
{
    public interface IPosition
    {
        double Left { get; set; }
        void MoveTo(double left, double top);
        double Top { get; set; }
    }
}

Create the helper class

using System.Windows.Controls;
using InheritenceSample.Interfaces;

namespace InheritenceSample.CompositionSample
{
    public class PositionHelper : IPosition
    {
        private UserControl userControl;

        public PositionHelper(UserControl userControl)
        {
            this.userControl = userControl;
        }

        public double Left
        {
            get
            {
                return (double) userControl.GetValue(Canvas.LeftProperty);
            }
            set
            {
                userControl.SetValue(Canvas.LeftProperty, value);
            }
        }

        public double Top
        {
            get
            {
                return (double)userControl.GetValue(Canvas.TopProperty);
            }
            set
            {
                userControl.SetValue(Canvas.TopProperty, value);

            }
        }

        public void MoveTo(double left, double top)
        {
            Left = left;
            Top = top;
        }

    }
}

Hang on we are almost there. To use this helper we need to add it to our control.

using System.Windows.Controls;
using InheritenceSample.Interfaces;
using InheritenceSample.CompositionSample;

namespace InheritenceSample
{
    public partial class MonkeyDesign2 : UserControl, IPosition
    {
        public IPosition position;

        public MonkeyDesign2()
        {
            // Required to initialize variables
            InitializeComponent();
            position = new PositionHelper(this);
            txtBaloon1.Text = "Arrived here through the stragey pattern";
        }

        public double Left
        {
            get
            {
                return position.Left;
            }
            set
            {
                position.Left = value;
            }
        }

        public void MoveTo(double left, double top)
        {
            position.MoveTo(left, top);
        }

        public double Top
        {
            get
            {
                return position.Top;
            }
            set
            {
                position.Top = value;
            }
        }
    }
}

Advantage:

demo download