Suppose that you have a UserControl and you want to merge some resources (which defines the styles, template and etc).
Suppose again that we cannot add the style to Application or Window, whereas you might conflict with styles that may be used by other part of the application (typical e.g. when the shell is designed by some developers but individual view is taken care by some other developers).
You may do something like this :
<UserControl x:Class="MyView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" > <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MyModule;component/Resource/Style/DarkStyles.xaml" /> <ResourceDictionary Source="pack://application:,,,/MyModule;component/Resource/Style/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources> </UserControl>
This sound OK, however, suppose there are many of them, and you might need to do the copy and paste more than once..
which sound OK at initial sight, but look at the possibility of a change, see rename to the styles, things get ugly with copy&paste.
Suppose that the UserControl may use one/a group of fixed styles, then it make sense to have some way that you can easily pick up the styles.
One things comes to us is the attached property. below is the impl which leverage the attachedProperty, which accepts a string (in Pack Uri format) to the target style.
here are the code.
namespace MyNamespace { public class ResourceLoader { public static string GetResourcePackUri(DependencyObject obj) { return (string)obj.GetValue(ResourcePackUriProperty); } public static void SetResourcePackUri(DependencyObject obj, string value) { obj.SetValue(ResourcePackUriProperty, value); } // Using a DependencyProperty as the backing store for ResourcePackUri. This enables animation, styling, binding, etc... public static readonly DependencyProperty ResourcePackUriProperty = DependencyProperty.RegisterAttached("ResourcePackUri", typeof(string), typeof(ResourceLoader), new UIPropertyMetadata(string.Empty, ResourcePackUriChanged)); private static void ResourcePackUriChanged(object sender_, DependencyPropertyChangedEventArgs args) { //DependencyPropertyDescriptor dpDescriptor = DependencyPropertyDescriptor.FromName("ResourcePackUri", typeof(ResourceLoader), if (sender_ == null) throw new ArgumentNullException("sender_"); //DependencyPropertyDescriptor dpDescriptor = DependencyPropertyDescriptor.FromName("ResourcePackUri", typeof(ResourceLoader), sender_.GetType()); //if (dpDescriptor != null) //{ //} var dpObject = sender_ as DependencyObject; if (dpObject != null) { if (dpObject is UserControl) { var usercontrol = (UserControl)dpObject; var uriInString = (string)args.NewValue; var uriOld = (string)args.OldValue; if (!string.IsNullOrEmpty(uriInString)) { Uri uri = new Uri(uriInString); ResourceDictionary resourceNew = new ResourceDictionary(); resourceNew.Source = uri; if (!string.IsNullOrEmpty(uriOld)) { var resourceOld = usercontrol.Resources.MergedDictionaries.FirstOrDefault<ResourceDictionary>(r => r.Source == new Uri(uriOld)); if (resourceOld != null) usercontrol.Resources.MergedDictionaries.Remove(resourceOld); } usercontrol.Resources.MergedDictionaries.Add(resourceNew); } else { throw new ArgumentException("ResourcePackUri only accepts string values"); } } else { // ?? throw new ArgumentException("AttachedProperty ResourcePackUri is only applicable on UserControl"); } } } } }
after this, you may do this to add the attached property to the UserControl.
<UserControl x:Class="MyNamespace.MyView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:MyNamespace" local:ResourceLoader.ResourcePackUri="pack://application:,,,/MyModule;component/Resource/Style/MergedStyles.xaml" > </UserControl>
and if you look at the pack://application:,,,/MyModule;component/Resource/Style/MergeStyles.xaml, you will see something like this:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="pack://application:,,,/MyModule;component/Resource/Style/DarkStyles.xaml"/> <ResourceDictionary Source="pack://application:,,,/MyModule;component/Resource/Style/Styles.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary>
Follow this discussion, we mihgt looks into how to make use of the Custom Markup Extension to accomplish the same task.