Should I split the themes into seperate dll's?

Coordinator
Nov 27, 2008 at 1:23 PM
I am considering creating multiple dll's for all the themes? Would this be OK? Then I could use something like MEF and specify a directory and it could dynamically locate all the available themes?

Please let me know what you think about this?

Thank you

Rudi
Nov 27, 2008 at 10:19 PM

As long as it is easy to save the user's selected theme.  I save the current theme in a settings file.  Retrieve theme when app loads with code below.  This is based on the your given strings "ExpressionDark", etc..

// Load theme on application level.

Application.Current.ApplyTheme(Properties.Settings.Default.ApplicationTheme);

Dec 1, 2008 at 10:18 AM
I'm not sure I'm the best qualified to answer this, but this sounds like a good plan to me. I plan on supplying a (very simple) theme of my own for my own application, and I guess users would love it if they could also choose from these professional looking ones.

As long as there is a simple way for an application to open the dll and apply the theme, this sounds like a dream come true! :)

Rune

Dec 4, 2008 at 8:52 PM
I think it could be easier to keep with one dll and only ship the theme files in a folder with a subdir for each theme. Then it would be easy to add or maintain themes by just adding or maintaining the XAML files (even in production environments).

Further I would suggest to rename the Theme.xaml files to eg. ExpressionDarkTheme.xaml because the resource panel of Blend just shows the filenames, not the folders. So you get lots of Theme.xaml which can't be distinguished. The rename would add the possibility to simply reference the theme file from eg. Application.xaml when dynamic change of themes is not required.

Great work, thanks!! Hope to see it grow.

Michael
Dec 28, 2008 at 7:17 AM
I really like the implementation that shaggygi has and agree with his statement that it's all good as long as it's easy to save and retrieve the theme based on a saved setting.
Coordinator
Jan 5, 2009 at 11:21 AM
Have a look here: http://dotnet.org.za/rudi/archive/2008/12/04/mef-taking-extensibility-to-the-next-level.aspx
Jan 5, 2009 at 1:05 PM
This approach looks very promising.  MEF is new to me, but seems this would be very easy to add the plugins/updates very easily.  I found it inconvenient to have to add the new update ( project ) for WPF themes in my apps each time there is an update and recompile.  I watched the BabySmash video and if the WPF Themes update will be easy as copying a DLL ( or few files ), then this would be great.

Few of questions.

1. When do you plan on releasing an example of this approach?  Please include a small tutorial/example app to help the slow coders like me.
2. I noticed something about the Directory the MEF is watching for plugins.  How does this work on deployed applications?  Will end users need to have the same directory structure on their machines? How will this work for using the ClickOnce/Publishing to network? 
3. Will this approach allow for other WPF Themes projects to work with our apps?  Meaning, if I or third party created themes ( not within your WPF themes ), would this work with our apps?
4. Will the approach I use for loading/saving the theme still work with this approach?  Currently use the code below to when app loads.

// Load theme on application level.
Application.Current.ApplyTheme(Properties.Settings.Default.ApplicationTheme);

5. How far do you plan on going with the WPF Themes project?  I really like what you have provided and can't wait to see what you release in future.  I understand other projects, personal life, etc. can get in the way of progress.  Would like to see a better roadmap if possible.  Any progress is good.  Would like to see TextBlock, ListView, TabControl, etc. added.

As usual, keep up the great work.
Jan 6, 2009 at 9:20 AM
All

I love the work being done here by Rudi.  I agree that the themes should be added in seperate dlls, and the MEF approach is definetely a good approach.  In the meantime however, if you wish to seperate out your themes, you can do so very easily using the following approach.

Create the library project to contain your theme.
Name it accordingly, for instance, MyNamepace.Wpf.Themes.BlackTheme
Create a subdirectory called themes, and another within that with the same name as your theme, e.g. Themes/BlackTheme
Within the BlackTheme subdirectory, add your Theme.xaml file.

This is all you need for your theme dll.  You then need to change to ThemeManager code as follows.  This method allows for having themes within the Themes dll or a separate library.

public static ResourceDictionary GetThemeResourceDictionary(string theme)
{
    if (theme != null)
    {
        //use the string to load an instance of the theme, from an external dll.
        var parts = theme.Split(';');

        var assembly = Assembly.GetExecutingAssembly();

        //if our parts length is equal to two, then we have specified an seperate dll also
        if(parts.Length==2)
        {
            var file = string.Concat(parts[1], ".dll");

            assembly = Assembly.LoadFrom(file);
        }

        //if parts length is 1, then assume theme is in this assembly
        AssemblyName name = assembly.GetName();

        string relativePackUriForResources =
            string.Concat("/", name.FullName, ";component/themes/", parts[0], "/", "Theme.xaml");

        Uri resourceLocater = new Uri(
            relativePackUriForResources, UriKind.Relative);

        return Application.LoadComponent(resourceLocater)
                   as ResourceDictionary;

    }
   
    return null;
}


To then use these themes in your application or control, you can use the attached theme property as follows:

themes:ThemeManager.Theme="BlackTheme;MyNamespace.Wpf.Themes.BlackTheme"

Separating the theme name and library with a semicolon.

This method is quick and easy approach to separate out you themes.  However, as I stated above, using the MEF approach could possibly be a better longer term solution, and is more configurable.

Michaels suggestion about having specifically named Theme files could also be catered for, just change the code to allow for setting the Theme.Xaml file name according to the theme name.

Cheers
Steve
Mar 20, 2009 at 12:36 PM
This is a great project! I took a look over the past weeks and its very exciting to see so many themes being offered in an open source project. Thanks a lot for making this available.

I see this thread is a bit old, but I wanted to give some feedback regarding separate DLL's and code structure that would help me to make use of this project. First, separate DLL's for the themes is a great idea. Especially when deploying applications, giving the flexibility of keeping that deployment light and only including what is initially needed is a big plus.

Secondly, I saw that WPF toolkit is on the roadmap. While its more of a pain to have more projects and more dll's, it would be extremely helpful if for each theme, the toolkit theme was in yet another separate DLL. This way those not using WPF toolkit would not need to have WPF toolkit in order to build the themes. For example, if I had a theme called TimsCoolYellow and I put it in a namespace like:

Tim.Wpf.TimsCoolYellow

I would only cover the controls included in the latest .NET framework. When I cover WPF toolkit with my theme, I'd do something like

Tim.Wpf.Toolkit.TimsCoolYellow

Then in project A, where I use toolkit all the time, I'd use both DLL's and bring in both resource dictionaries. In project B, where I don't use the toolkit, I would only bring in the first assembly.

Finally, lets say I'm using Joe's Data Grid, which doesn't match any of the themes I have, but I really want to make it match TimsCoolYellow. I could create Tim.Wpf.Joe.TimsCoolYellow bring it in on the project I'm using that particular vendors controls only.

An argument against this may be that the TK controls are going to be part of a future version of the WPF release anyway, so its fine to package them together - just use the toolkit. However, the real value added is going to be where you have the flexibility in the code that allows users to select and switch between themes, to be able to look up optional extensions to a theme based on what the developer wanted to include (in the case of custom themes for third party vendor controls). At least for me, as I'm making use of some third party controls, I'd be much more likely to use the themes here if this separation was put in place.