Saturday 28 July 2007

Inheriting a control from the Silverlight 1.1 Alpha Refresh Control Toolkit

I've just found a small bug in the ControlBase of the Silverlight 1.1 Alpha Refresh Silverlight UI Controls project.

I was attempting to create my own button which inherits ButtonBase. I used Button as an example and discovered the following problem.

If you create your new control outside of the SilverlightUIControl project, and use an embedded xaml file, unfortunately your button will not work.

This is because ControlBase will only look at resources in the Assembly in the SilverlightUIControls assembly.

I have implemented a workaround (messy code, but nonetheless it does the job). I have posted it below (all you need to do is replace the constructor in ControlBase).

I hope the guys at MS fix this:



public ControlBase()
{
//the control template must be in an embeded resource - find it
Stream resourceStream = null;
//if the assembly is built with VS there will be a prefix before
//the resource name we expect. The resource name will be at the
//end after a dot
string dotResource = '.' + ResourceName;
Assembly assembly = typeof(ControlBase).Assembly;
string[] names = assembly.GetManifestResourceNames();
bool found = false;
foreach (string name in names) {
if (name.Equals(ResourceName) || name.EndsWith(dotResource)) {
resourceStream = assembly.GetManifestResourceStream(name);
found = true;
break;
}
}

if (!found)
{
Assembly currentAssembly = this.GetType().Assembly;
string[] currentNames = currentAssembly.GetManifestResourceNames();
foreach (string name in currentNames)
{
if (name.Equals(ResourceName) || name.EndsWith(dotResource))
{
resourceStream = currentAssembly.GetManifestResourceStream(name);
found = true;
break;
}
}
}

Debug.Assert(resourceStream != null, "the resource template" + ResourceName + " not found");
StreamReader sr = new StreamReader(resourceStream);
string xaml = sr.ReadToEnd();
actualControl = InitializeFromXaml(xaml);
sr.Close();
Debug.Assert(actualControl != null, "failed to initialize the control");

base.Width = actualControl.Width;
base.Height = actualControl.Height;

Loaded += new EventHandler(OnLoaded);
}

No comments: