0

I am writing Style Setters for custom WPF controls and would like to set values to resources (such as Brushes) that would ideally (read "hopefully") be defined at an application-level (so that app-wide theming is enabled). One example would look something like this:

<Style.Triggers>      
    <DataTrigger Binding="{Binding IsInteresting}" Value="True">
        <Setter Property="FontWeight"   Value="Bold" />
        <!-- Use the brush that is (hopefully) defined at the application-level -->
        <Setter Property="Foreground"   Value="{StaticResource InterestingBrush}" />
    </DataTrigger>
</Style.Triggers>

Now to make the Style usable in the case that the resource has not yet been defined at the application-level, I would like to be able to define the brush locally in Xaml and have that definition be used if a resource with that same key is not found elsewhere. Conceptually speaking, it would be analogous to using an "if not defined" preprocessor directive such as #ifndef.

Perhaps there already exists a mechanism for doing this. If not, how could it be implemented? Could an attached property/behavior somehow do this? If so, I envision its usage looking something like this:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                xmlns:HopefulBehaviors="clr-namespace:HopefulBehaviors"
                xmlns:My_Controls="clr-namespace:My_Controls"
                >
    <!-- IDEA:
         Attached property being used to "use the brush that is defined elsewhere
         if it was found, if not use this locally-defined one" -->
    <SolidColorBrush x:Key="InterestingBrush" 
                     HopefulBehaviors:UseExternalIfFound="True" Color="Red"  />

    <Style TargetType="{x:Type My_Controls:AwesomeControl}">

        <Style.Triggers>
            <DataTrigger Binding="{Binding IsInteresting}" Value="True">
                <Setter Property="FontWeight" Value="Bold" />
                <!-- now this brush would be defined (at least locally
                       but an external definition is used if it is found) -->
                <Setter Property="Foreground" Value="{StaticResource InterestingBrush}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</ResourceDictionary>

I realize that one workaround might be to leave the generic custom control Style pretty bland, then write inherited Styles that for each application that use references to resources that exist in that application. But I'm hoping there is a more elegant approach that generalizes across applications better.

Jason Frank
  • 3,842
  • 31
  • 35
  • `Resources` works in same way as any object in class. If variable `a` is defined within method body any reference to variable a will be resolved with local copy but in case if not present then class level field will be used. So, if you declared resource with same name, any reference to resource will be resolved locally and it won't travel up for resolving it..! – Rohit Vats Mar 27 '13 at 17:25
  • 1
    Right - that's the _default_ behavior, but not what I want. That's why I gave the #ifndef analogy and why I showed the idea of the attached property altering the default behavior. So the desired behavior would be more like "travel up and try to resolve it, but if you can't find anything then use this definition" - exactly like the #ifndef. – Jason Frank Mar 27 '13 at 17:38
  • @Jason - I believe the simplest is to just add `` - to any UserControl or resource that uses it. As well as into App if you'd want (best is to make your mind up, organize). That way you don't `duplicate` things - you use `one file` which you can share - and whichever comes first (scope) is used. Let me know if that'd do for you. Just an advice - don't over-complicate things:) – NSGaga-mostly-inactive Mar 27 '13 at 17:56
  • @NSGaga The idea is that while I'm developing the Style for the custom controls, I can go ahead and include generic resource names in the Style Setters and test those styles before exact colors for an app-wide theme has been developed. Once the app-wide theme comes along, then those resources would take precedence. Additionally, having the "fallback" resources defined locally in the Style file makes it very portable and eases development on it without relying on the app-wide theme to be present in all contexts. In this way, it actually would simplify development. – Jason Frank Mar 27 '13 at 18:09
  • I know this question is old, and maybe you've already figured it out. But... for what I think you're trying to do, the more typical way would be for your custom control to set a default value (always), and then for the application to use a style to override the default (where the `TargetType` of the style is your custom control type). Without a good [mcve] showing exactly what your scenario is, I can't provide any sort of detailed answer, but it does seem to me that WPF offers a idiomatic way to solve this issue, without the need for added implementation (like the attached property idea). – Peter Duniho Mar 04 '16 at 01:52

0 Answers0