Tuesday, 17 June 2008

Silverlight 2.0 Beta 2 - Creating a user control to be used as a base class

Little tip here that I worked out whilst trying to get the ShellBase class from Silverstone working in the XAML editor and Expression blend.

I started off with an abstract class which derived from UserControl, like follows:

    public abstract class ShellBase : UserControl, IShell

    {

        //... some code

    }

Unfortunately, neither Expression Blend nor Visual Studio's Cider designer likes this, they need to create an instance of the base class for some reason. You get an error message saying it couldn't create an instance of it. Removing the abstract constraint solves this (though violates OO, but I don't mind in this instance!).

Now I have some XAML which looks like this for defining my actual Shell:

<Silverstone:ShellBase x:Class="Silversocial.Client.Views.Shell"

   xmlns="http://schemas.microsoft.com/client/2007"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   xmlns:Silverstone="clr-namespace:Silverstone;assembly=Silverstone">

    <Grid x:Name="LayoutRoot" Background="Black">

 

    </Grid>

</Silverstone:ShellBase>

VS and blend now complain because ShellBase does allow content to be added. The solution I discovered was fairly simple and was twofold:

1. Add a property called Content which shadows the UserControl's Content property and redirects to it

2. Add a ContentProperty attribute to the ShellBase which points to the Content property

    [ContentProperty("Content")]

    public class ShellBase : UserControl, IShell

    {

        /// <summary>

        ///    Redefine the base class's content property to keep the designers happy

        /// </summary>

        public new UIElement Content

        {

            get { return base.Content; }

            set { base.Content = value; }

        }

And that's it! Designer support enabled!

Hope this helps...

Neil

Update - 20/06/2008

It appears I was wrong about the ContentProperty attribute, it doesn't work. See this post for more info

2 comments:

Greg F said...

I got it to work using this:

[ContentProperty("Content")]
public class ShellBase : UserControl
{
public new UIElement Content { get; set; }

If I specified base.Content as the storage it threw exceptions. Using Silverlight 2 RTW.

Neil Mosafi said...

Nice one! Thanks for letting me know. I had't had a chance to retest this on Silverlight RTW, so assume it now all works as expected!

Neil