Loading x:Class XAML Controls

Posted by Rishi on 22-Mar-09 9:32 AM - Comments (0)

Tags: , , | Categories: .NET, Silverlight, Code

In Silverlight we have two models of .xaml controls, with and without code files. Loading plain xaml files is easy, however when you try and load code-backed xaml using the XamlReader it errors saying "does not support x:Class". Goggling I couldn't find any listed ways out, but I found a way though it - which is by loading it as xml first, then extracting the class name and finally instantiating it. There is the assumption of no arguments in my code, but if you have the type it can be resolved and in cases where you don't know if it is xClass based you can open the file with the xml reader check for that specifically. This might be a bit hacky but it works, have a look..

const string RESOURCE_PATH = "/{0};component/{1}";   // the format is ==> /AssemblyName;component/ResourceFilePathName

public UIElement LoadXaml(string assemblyFullyQualifiedName, string xamlPathFileName, bool xClassType)
{

    // and we try and load thew resource
    var _uri = new Uri(
        string.Format(RESOURCE_PATH, GetAssemblyName(assemblyFullyQualifiedName), xamlPathFileName), UriKind.Relative);
    var _streamResourceInfo = Application.GetResourceStream(_uri);

    using (var _stream = _streamResourceInfo.Stream)
    {

        return (xClassType ? XamlXClassLoader(_stream, assemblyFullyQualifiedName) : XamlLoader(_stream)) as UIElement;

    }

}

Object XamlLoader(Stream stream)
{
    using (var _reader = new StreamReader(stream))
    {
        return XamlReader.Load(_reader.ReadToEnd());
    }
}
    
Object XamlXClassLoader(Stream stream, string assemblyName)
{

    // we load the content as xml
    using (var _xmlReader = XmlReader.Create(stream))
    {
        // the control should be the root element
        if (_xmlReader.Read())
        {

            // we get the x:Class attribute's value
            var _classTypeName = _xmlReader.GetAttribute("Class", "http://schemas.microsoft.com/winfx/2006/xaml");

            // assembly name is required, else we take the assumption it is the application's assembly
            var _assemblyName = !string.IsNullOrEmpty(assemblyName)
                ? assemblyName : Application.Current.GetType().Assembly.FullName;

            // we load the class type defined in the x:Class attribute
            var _type = Type.GetType(_classTypeName + "," + _assemblyName, false, true);

            // we load the type
            if (_type != null)
            {
                var _xamlControl = Activator.CreateInstance(_type);     // note, the assumption of no args

                // and we return
                return _xamlControl;
            }

        }
    }

    // else
    return null;

}

string GetAssemblyName(string assemblyFullyQualifiedName)
{
    return assemblyFullyQualifiedName.Substring(0, assemblyFullyQualifiedName.IndexOf(','));
}

This surely applies to SL2, maybe in SL3 their might be a way to get xaml controls directly, as they have baked in a navigation framework that seemingly instantiates existing xaml controls via it's relative file path - have to check though.

Add comment


(Will show your Gravatar icon)

  Country flag

biuquote
  • Comment
  • Preview
Loading