tags:

views:

56

answers:

1

I'm just diving into WPF and find this a little odd and frustrating to my style: Why can the value of something be a Resource but you can't set the value directly to what the Resource represents? Example:

This is valid:

<ToggleButton>
    <ToggleButton.Resources>
        <Image x:Key="cancelImage" Source="cancel.png" />
    </ToggleButton.Resources>
    <ToggleButton.Style>
        <Style TargetType="{x:Type ToggleButton}">
            <Setter Property="Content" Value="{DynamicResource cancelImage}" />
        </Style>
    </ToggleButton.Style>
</ToggleButton>

But this is not:

<ToggleButton>
    <ToggleButton.Style>
        <Style TargetType="{x:Type ToggleButton}">
            <Setter Property="Content">
                <Setter.Value>
                    <Image Source="cancel.png" />
                </Setter.Value>
            </Setter>
        </Style>
    </ToggleButton.Style>
</ToggleButton>

What is the difference? Why don't both work? I don't like having to create a "Resource" for some things because it divides my code up and can make it more difficult to read.

And yes, I do know my example can be simplified like this

<ToggleButton>
    <Image Source="cancel.png" />
</ToggleButton>

but that's not the point.

+3  A: 

When working with setters, the value for the setter has to support the ability to be "frozen". That can be a value type (including structs and enums), or a class that derives from Freezable.

It may not help your aesthetic sense much, but it is often cleaner to declare all your resources at the top of the Resources section of the file (or ResourceDictionary), as opposed to adding them to the Resources of an individual style or control.

Abe Heidebrecht
This tripped me up for awhile. Once you realize the performance benefits of something being frozen, it makes sense why MS forces values for setters to be freezable.
unforgiven3
So you're saying by making an <Image /> a Resource, I am freezing it? Otherwise, I may have the opportunity to change a property of the <Image /> at run time, which is a performance burden for the layout/drawing subsystem. Is that the gist of it?
tyriker
No, it isn't being frozen, the StaticResource is the element in the setter that is frozen. When the template's visual tree is created, it can then find the non-frozen Image element. Since Image doesn't derive from Freezable, it can't be frozen, unfortunately, which is why you can't use it in a setter.
Abe Heidebrecht
Thanks Abe. This page (http://msdn.microsoft.com/en-us/library/ms750509.aspx) helped my fully understand your answer.
tyriker