Tim wrote a great blog post a while ago about the new JetPack theme for Silverlight that’s available for download along with its friends. You can try them all on the web by clicking on the images below;
If I wanted to use these in Blend I can grab the download of the raw assets from the website;
and then extract those out somewhere giving me;
Then I can launch into Blend, begin a new Silverlight project and add items;
and I choose ( from the JetPack theme );
because I’m not planning to use the SDK controls or the Toolkit controls in my application.
Blend brings these in and the Resources tab shows what’s gone on;
but I hit a “problem” in that I need to add a reference to the System.Windows.Controls.Navigation.dll assembly as there’s styles in those XAML files that hit controls in that assembly.
With that added all my styles are now fine and if I draw out a Button onto the artboard I see it drawn in its new default style and I can apply one of the other resources to it;
What if I wanted to bring in both JetPack and Windows theme? Easy enough. I can create a couple of folders with the 2 sets of assets in different sub-folders;
and then make sure all my resources are linked up the right way;
and then just by changing that top link in App.xaml to switch between jetpack.xaml and windows.xaml I get the switch I want;
what if I wanted to change these at runtime based on some user action. I think I’d need a little code and an Action might just work. Here’s a very quick one I threw together;
using System; using System.IO; using System.Windows; using System.Windows.Interactivity; using System.Windows.Markup; using System.Windows.Resources; namespace SilverlightApplication46 { public class ChangeGlobalAppDictionaryAction : TriggerAction<DependencyObject> { public static DependencyProperty ResourceDictionaryUriProperty = DependencyProperty.Register("ResourceDictionaryUri", typeof(Uri), typeof(ChangeGlobalAppDictionaryAction), new PropertyMetadata(null)); public Uri ResourceDictionaryUri { get { return ((Uri)base.GetValue(ResourceDictionaryUriProperty)); } set { base.SetValue(ResourceDictionaryUriProperty, value); } } protected override void Invoke(object parameter) { StreamResourceInfo resourceInfo = Application.GetResourceStream(this.ResourceDictionaryUri); if (resourceInfo != null) { using (StreamReader reader = new StreamReader(resourceInfo.Stream)) { string xaml = reader.ReadToEnd(); ResourceDictionary newDictionary = XamlReader.Load(xaml) as ResourceDictionary; if (newDictionary != null) { ResourceDictionary appDictionary = Application.Current.Resources; // runs the risk of throwing away things we don't want it to. appDictionary.MergedDictionaries.Clear(); appDictionary.MergedDictionaries.Add(newDictionary); } reader.Close(); } } } } }
and so I can now make use of that from some piece of UI. I’ll add a few random UI elements to my artboard and I’ve left the App.xaml unlinked to either of the 2 themes by default. Then I’ve set this ComboBox in the top right here;
so that its Items point to 2 strings which define the URI’s to my jetpack.xaml and windows.xaml
and I can make the ComboBox.SelectionChanged event fire my Action;
making sure to bind the ResourceDictionaryUri property on my Action to the SelectedValue on my ComboBox and that works ok in that I can run my app and view it in its 3 styles;
although, naturally, I wouldn’t want to display those URIs to the user in that ComboBox