Custom BindingExtension to set Resource/Styles

In Previous post - Use an attached Property to set Resources/Styles , we discussed how to leverage the Attached property to easily set the resources/styles for a user control.

 

Follow the discussion on Custom WPF Binding Markup Extension, there is an alternative approach that makes use of the BindingExtension. 

 

The following discussion uses the BindingDecoratorBase, a class that is contributed in the post of Custom WPF Binding Markup Extension.

 

 

The code that imple the BindingExtension is as follow.

 

 

namespace Com.Boqwang.Utils
{
  // below is modeled after the code described here 
  // http://www.hardcodet.net/2008/04/wpf-custom-binding-class
  /// <summary>
  /// MyCustomBinding example/
  /// </summary>
  public class CustomResourceExtension : BindingDecoratorBase
  {

    /// <summary>
    /// the resource in PackUri format
    /// </summary>
    public string ResourcePackUri { get; set; }

    public override object ProvideValue(IServiceProvider provider)
    {
      object val = base.ProvideValue(provider);

      DependencyObject targetObject;
      DependencyProperty targetProperty;

      bool status = TryGetTargetItems(provider, out targetObject, out targetProperty);

      if (status)
      {
        // in this branch, the targetObject as well as the targetProperty should both be Non-null
        if (targetProperty.Name != "Style")
        {
          throw new InvalidOperationException("TargetProperty 'Resources' required!");
        }

        var control = targetObject as UserControl;
        if (control == null)
        {
          //throw new NotSupportedException("
          throw new InvalidOperationException("TargetObject 'UserControl' required!");
        }

        if (string.IsNullOrEmpty(ResourcePackUri))
        {
          throw new InvalidOperationException("'ResourcePackUri' cannot be Null or Empty");
        }

        Uri uri = new Uri(ResourcePackUri);
        ResourceDictionary resource = new ResourceDictionary();
        resource.Source = uri;

        if (control.Resources.MergedDictionaries.FirstOrDefault(r => r.Source == uri) == null)
        {
          control.Resources.MergedDictionaries.Add(resource);
        }
      }
      else
      {
        throw new InvalidOperationException("Undefined DependencyObject or DependencyProperty");
      }

      return val;
    }
    
  }
}
 

 

To make this work, I overloads the use of Style DepedencyProperty. Let's see how to use the MarkupExtension.

 

 

<UserControl x:Class="MorganStanley.FutOpt.TRecsSupportModule.View.DashboardView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:local="clr-namespace:Com.Boqwang."
             >
  
  <UserControl.Style>
    <local:CustomResourceExtension  ResourcePackUri="pack://application:,,,/MyModule;component/Resource/Style/MergedStyles.xaml" />
  </UserControl.Style>
 

 

and as the previous post, the MergedStyles.xaml file looks liks 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:,,,/TRecsSupportModule;component/Resource/Style/DarkStyles.xaml"/>
    <ResourceDictionary Source="pack://application:,,,/TRecsSupportModule;component/Resource/Style/Styles.xaml"  />
  </ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
  

 

 

The code here are suject to future changes.

 

 

 

 

 

你可能感兴趣的:(Custom BindingExtension to set Resource/Styles)