Silverlight usercontrol inheritance
Demo and source code included below. 
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:
- This method is very good when creating an application or game
which makes heavy use of multiple XAML files which or focused on
design.
- You can change between multiple designs (XAML files) by just
changing the usercontrol property.
Disadvantage:
- You need to create a extra file foreach control.
- The usercontrol is only accessible throught the UserControl
property
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:
- When using composition its easy to change the position behavior
at runtime.
- Using composition over inheritance decouples your classes
