4

I'm implementing my own markup extension to make sure color resources show up properly in the XAML designer in Visual Studio. Basically I have a special version of DynamicResource that returns a certain resource when in design mode.

My plan was simply to derive from DynamicResourceExtension and in ProvideValue do special code when in design mode and just call the base class when in normal mode.

The problem is that when I inherit from DynamicResourceExtesion, it doesn't seem like my overridden ProvideValue method gets called.

I'm strongly suspecting this is a bug in the framework but I want to post here in case I'm missing something obvious.


Here are two version of the same extension, one that works and one that doesn't:

Composition version - this works as expected

public class MyResourceComposition : MarkupExtension
{
    private readonly DynamicResourceExtension m_dynamicResource = new DynamicResourceExtension();

    public MyResourceComposition()
    {}

    public MyResourceComposition(string resourceKey)
    {
        ResourceKey = resourceKey;
    }

    public object ResourceKey
    {
        get { return m_dynamicResource.ResourceKey; }
        set { m_dynamicResource.ResourceKey = value; }
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (Helper.IsInDesignMode)
            return Brushes.Blue;

        return m_dynamicResource.ProvideValue(serviceProvider);
    }
}

Inheritance version - this does not work

public class MyResourceInheritance : DynamicResourceExtension
{
    public MyResourceInheritance()
    {}

    public MyResourceInheritance(string resourceKey)
        :base(resourceKey)
    {
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (Helper.IsInDesignMode)
            return Brushes.Blue;

        return base.ProvideValue(serviceProvider);
    }
}    

This is the XAML I use to test it:

<UserControl.Resources>
    <SolidColorBrush Color="Green" x:Key="MyBrush" />
</UserControl.Resources>

<StackPanel>
    <!-- This will be green at design time: OK! -->
    <Rectangle Fill="{DynamicResource ResourceKey=MyBrush}" Width="50" Height="50" Margin="8" />
    <!-- This will be green at design time: NOT OK! -->
    <Rectangle Fill="{local:MyResourceInheritance ResourceKey=MyBrush}" Width="50" Height="50" Margin="8" />
    <!-- This will be green at design time: OK! -->
    <Rectangle Fill="{local:MyResourceComposition ResourceKey=MyBrush}" Width="50" Height="50"  Margin="8" />
</StackPanel>

For completeness, here's how I figure out if I'm in design mode (but it doesn't matter - even if I unconditionally return Brushes.Blue from ProvideValue() I get the dynamically looked up value.)

internal static class Helper
{
    private static bool? s_isInDesignMode;

    public static bool IsInDesignMode
    {
        get
        {
            if (!s_isInDesignMode.HasValue)
            {
                var prop = DesignerProperties.IsInDesignModeProperty;
                s_isInDesignMode
                    = (bool)DependencyPropertyDescriptor
                                .FromProperty(prop, typeof(FrameworkElement))
                                .Metadata.DefaultValue;
            }

            return s_isInDesignMode.Value;
        }
    }
}
Isak Savo
  • 34,957
  • 11
  • 60
  • 92
  • Out of curiosity, what if you were to place the inheritance `Rectangle` below the composition `Rectangle`? Perhaps this is an issue with the `IsInDesignMode` property. Maybe it's not being loaded first time? – Mike Eason Oct 07 '15 at 12:15
  • Unfortunately not @MikeEason. The MyResourceInheritance rectangle is green regardless of position. – Isak Savo Oct 07 '15 at 12:57
  • Might consider a [different way](http://stackoverflow.com/questions/32872212/create-properties-that-only-apply-on-design-time/32874861#32874861). – Chris W. Oct 07 '15 at 13:28

0 Answers0