Navigation


Markus on Development and Publishing

This is Markus Egger's professional blog, which covers topics such as development, publishing, and business in general. As the publisher of CoDe and CoDe Focus magazines, and as the President and Chief Software Architect of EPS Software Corp., Markus shares his insights and opinions on this blog.

Content Area Footer

Monday, October 05, 2009
Dynamically Loading Resource Dictionaries in Silverlight 3

At this fall’s BASTA conference in Mainz, I presented a session on “Reusable Silverlight Components”. One of the things I showed in that session was how to create Silverlight components that can be hosted in different sites and also be completely re-styled and rebranded by means of dynamically loaded Resource Dictionaries.

Silverlight v3 is the first version of Silverlight that supports resource dictionaries. This makes it much easier to maintain resources generically in separate XAML files, and even switch between different sets of resources. One of the possibilities that often goes overlooked however, is that resource dictionaries can be loaded completely dynamically from any URL. I often use this in scenarios where I pass parameters to a Silverlight control, where one of the parameters is the URL of such a resource dictionary. I then load that dictionary dynamically, so everything in that application references that dictionary. The basic idea is the dynamic load process from a URL. This can be done like so:

WebClient request = new WebClient();
request.DownloadStringCompleted +=
    new DownloadStringCompletedEventHandler(request_DownloadStringCompleted);
request.DownloadStringAsync(
    new Uri("http://domain.com/mydictionary.xaml", UriKind.Absolute));

This triggers an asynchronous string download from the specified URL. The associated event handler fires when the download is complete and assigns the loaded resource dictionary:

void request_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    string resourceXaml = e.Result;
    ResourceDictionary dictionary =
        Application.Current.Resources as ResourceDictionary;
    dictionary.MergedDictionaries.Add(
        (ResourceDictionary)XamlReader.Load(resourceXaml));
}

This accesses the current application resources (which should be a resource dictionary, although some error handling may be appropriate here) and then uses a XamlReader to load the retrieved XAML string, casts it to a resource dictionary (which it may not be, so more error handling is in order here) and then simply adds it to the collection of available resource dictionaries.

There are a few more things of interest here that are worth pointing out:

First of all, Silverlight 3 still doesn’t support dynamic resources. Static resources get assigned as soon as an interface loads and can’t be changed later. This means that the new resource dictionaries should be added before any real UI loading is done. I generally like to allow for a “resourcedictionaries” parameter passed to the Silverlight control, but I make the parameter optional. For this reason, I generally have this kind of code in my Startup event handler in App.xaml.cs:

private void Application_Startup(object sender, StartupEventArgs e)
{
    if (e.InitParams.ContainsKey("resourcedictionary"))
    {
        var content = new Grid();
        this.RootVisual = content;
        content.Children.Add(new LoadingAnimation());
       
       
WebClient request = new WebClient();
        request.DownloadStringCompleted +=
            new DownloadStringCompletedEventHandler(request_DownloadStringCompleted);
        request.DownloadStringAsync(
            new Uri(e.InitParams["resourcedictionary"], UriKind.Absolute));
 
    }
    else
    {
        var root = new Page1();
    }
}

This code checks for the parameter. If it isn’t present, the root UI (Page1.xaml in this case) is loaded right away. Otherwise, I create a Grid() as a root container (the RootVisual setting can only be assigned once, so I am using the Grid object as a container which I can then use to load other UI into) and I then load a temporary loading screen while resource dictionaries are downloaded (you never know how long that might take). Then, when the dictionary is downloaded, I merge it into the resources and then I load the real UI into the Grid:

void request_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
    string resourceXaml = e.Result;
    ResourceDictionary dictionary =
        Application
.Current.Resources as ResourceDictionary;
    dictionary.MergedDictionaries.Add(
        (ResourceDictionary)XamlReader.Load(resourceXaml));

    var grid = this.VisualRoot as Grid;
    grid.Children.Clear();
    grid.Children.Add(new Page1());
}

Using this approach, the main UI (Page1) gets loaded after the custom dictionaries are downloaded and thus all static resources pick up the new styles.

Note: If you use the Implicit Style Manager, some of this is not as critical, since the ISM manually applies styles whenever it is invoked. However, since you are likely to still use named styles (which are always static), you probably still have the same problem.

Another interesting thing to note here is that I am simply adding the new dictionaries to the collection of merged dictionaries. The way Silverlight looks up resources, the resources added last are found first. So if my application already has a dictionary with a style called “StandardButtonStyle” and a dictionary that is added later also has a style of the same name, the one loaded last is found and used. This means that dynamically loaded resource dictionaries can define a few new styles as needed. Since the standard resource dictionaries remain in place, Silverlight will find all the default styles there, but the new dictionaries can override only specific ones. If you completely replace all of the application’s resources, then the newly loaded dictionaries would have to define every single resource or else the control would show an error and probably fail to load. So adding resource dictionaries in addition is generally a nifty technique that works very well in the real world.

 



Posted @ 12:14 PM by Egger, Markus (markus@code-magazine.com) -
Comments (6)




Comments:

RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Tuesday, October 13, 2009 4:17 PM by Brian Foote - brian@gurubyte.com

This is a great tip, thanks!


RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Thursday, November 26, 2009 5:27 AM by franctum

Very useful, thank you!


RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Friday, November 27, 2009 8:59 AM by Leeladharan MP - leelu@in-source.com

Great Post!!


RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Wednesday, December 23, 2009 10:16 AM by Maurizio

You resolved my problem, thank you very much!


RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Thursday, July 22, 2010 4:04 AM by wedding - tombupliy@gmail.com

What a great read, they couple looks truly looks happy. Thank you for sharing.


RE: Dynamically Loading Resource Dictionaries in Silverlight 3
Thursday, July 22, 2010 4:10 AM by wedding - tombupliy@gmail.com

supply in stock and custom lace front wigs, full lace wigs, lace wigs, human hair wigs, remy lace front wigs, cheap wigs, cheap, buy, celebrity full lace wigs lace wigs lace wigs sale lace front wigs synthetic front lace wigs Full Lace Front Wig, Long & Short Hair Wigs: 80% OFF at Celebrity Wigs. We ensure 100% customer satisfaction with our Long & Short Indian Remy Hair Wigs. wedding dresses evening dresses prom dresses




Post a Comment:

Comment Title (required)

Your Name (optional)

Your Email (optional)

Your Web Site (optional)

Your Comment (required)

 

 

 

 

 

 

 



My Twitter Status


    follow me on Twitter  


    Geo Caching
    Profile for MarkusEgger

    Syndication RSS 2.0 RSS 2.0

    All My Blogs:
    My personal blogs:
    Dev and Publishing Dev and Publishing
    Travel and Internat. Living Travel and Internat. Living
    Other blogs I contribute to:
    Milos Blog (US) Milos Blog (US)
    VFPConv. Dev Blog (US) VFPConv. Dev Blog (US)
    VFPConv. Dev Blog (DE) VFPConv. Dev Blog (DE)

     

    Blog Archives
    All Blog Posts

    2010
        July (1)
        June (1)
        April (3)
        March (1)
        February (5)
        January (1)
    2009
        October (4)
        September (2)
        August (1)
        July (1)
        May (4)
        April (6)
        February (1)
        January (1)
    2008
        December (3)
        November (11)
        October (8)
        September (1)
        July (1)
        June (3)
        May (3)
        April (6)
        March (6)
        February (4)
    2007
        December (1)
        November (1)
        October (5)
        September (1)
        August (1)
        July (6)
        June (3)
        May (3)
        April (1)
        March (2)
        January (2)
    2006
        December (3)
        November (4)
        October (1)
        September (2)
        August (2)
        July (4)
        June (1)
        May (2)
        April (10)
        March (2)
        February (3)
        January (1)
    2005
        December (6)
        November (7)
        October (6)
        September (8)
        August (10)
        July (6)
        June (9)

     

     

     

    This Blog is powered by MilosTM Collaboration Components.