Silverlight 2 (beta1): User Control Inheritance

We have been discussing about how to inherit a Silverlight page or Silverlight control from the base class lately in Silverlight Forum. (You can read our discussions here, here, here and here.) As the most of .NET developers have the ASP.NET background, we all want to have the base class/master page that can be inherited from other controls. Unlike ASP.NET Master Page, it’s a lit bit tricky to do inheritance in Silverlight. In this post, I’m gonna give you the step-by-step guide for that.

User Control Inheritance in Silverlight

Note: As you know, you can change the name as you like but I will use the following names in my sample.

1. Create new silverlight project called “SL2Controls”

2. Add a class called BaseControl

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SL2Controls {
public class BaseControl : UserControl {

}
}

3. Add Silverlight User control called “InheritedControl”

XAML


<BaseControl x:Class="SL2Controls.InheritedControl"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="Red">

</Grid>
</BaseControl>

C#


using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SL2Controls {
public partial class InheritedControl : BaseControl {
public InheritedControl() {
InitializeComponent();
}
}
}

4. Add mapping in AssemblyInfo.cs under Properties of SL2Controls


using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows.Markup;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("SL2Controls")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SL2Controls")]
[assembly: AssemblyCopyright("Copyright ©  2008")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
[assembly: XmlnsDefinition("http://schemas.microsoft.com/client/2007", "SL2Controls")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components.  If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]

// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("27885afb-0308-473e-9773-73350bc1555f")]

// Version information for an assembly consists of the following four values:
//
//      Major Version
//      Minor Version
//      Build Number
//      Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

5. Add this Inherited control to Page.xaml.


<UserControl x:Class="SL2Controls.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myctl="clr-namespace:SL2Controls"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<myctl:InheritedControl/>
</Grid>
</UserControl>

then, run the application. (You don’t need to update *.g.cs file.)

Download Source: http://michaelsync.net/demo/SL2Controls.zip

There is one weakness in this trick. You will lost the designer in InheritedControl.xaml but you won’t get any error. If you want to know how to do for Silverlight page, you can read the second post in this link.

Yes. As we all are new to Silverlight 2 beta1, we probably need to explore more thing about it. Feel free to discuss with me if you have any comment or suggestion.

Update: If you don’t add namespace mapping in assembly, I think it will be working fine. but this is a known issue that will fix in next release. Yi-Lun from Microsoft said as below ~

Hello, there’re some issues related to UserControl inheriting that we’re investigating… I’m surprised to see this works:

<MyUserControlBase x:Class=”SL2Test.Page”
xmlns=”http://schemas.microsoft.com/client/2007″
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
Width=”400″ Height=”300″>
<Canvas Width=”400″ Height=”300″ Background=”Red”>
</Canvas>
</MyUserControlBase>

Actually it shouldn’t work. MyUserControlBase is not in the namespace http://schemas.microsoft.com/client/2007. This xml namespaces maps to a series of clr namespaces such as System.Windows.Controls. But there’s no way it can map to your own namespace. Also this behavior is inconsistent with WPF.

This is likely to be a bug. I’ll redirect this to our product team. Thanks for letting us know.

You’re right. This can be a work round.

In the class library project’s AssemblyInfo.cs file, add this:

[assembly: XmlnsDefinition("http://schemas.microsoft.com/client/2007", "YourNamespace")]

Now after you add reference to this assembly in your main project, you can use any classes in this namespace in your XAML files.

But without the namespace mapping, your original code should not work. So this still seems to be an issue…