Search code examples
wpfxamltemplatebindingwpf-style

TemplateBinding not working inside a DrawingImage in a Button Style


I want to use a GeometryDrawing as a button icon, inside a ControlTemplate, and I want its Brush property to be bound to the button's Foreground property, but it's not working. On the other hand, if I set the Brush explicitly, it works.

Here is my (non-working) code:

    <Style x:Key="SimpleButtonStyle" TargetType="{x:Type Button}">
        <Setter Property="Background" Value="LightGray"/>
        <Setter Property="Foreground" Value="Black"/>
        <Setter Property="BorderThickness" Value="2"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type Button}">
                    <Border x:Name="border" 
                            BorderBrush="{TemplateBinding Foreground}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            SnapsToDevicePixels="true">
                        <StackPanel Orientation="Vertical">
                            <Image x:Name="buttonImage" Height="20" Width="20">
                                <Image.Source>
                                    <DrawingImage>
                                        <DrawingImage.Drawing>


                                            <!-- line below does not work -->
                                            <GeometryDrawing Brush="{TemplateBinding Foreground}">


                                                <GeometryDrawing.Geometry>
                                                    <EllipseGeometry RadiusX="15" RadiusY="15"/>
                                                </GeometryDrawing.Geometry>
                                            </GeometryDrawing>
                                        </DrawingImage.Drawing>
                                    </DrawingImage>
                                </Image.Source>
                            </Image>
                            <ContentPresenter x:Name="contentPresenter"/>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

Solution

  • See this WPF TemplateBinding vs RelativeSource TemplatedParent - Paul Fischer's answer. In particular, this part regarding TemplateBinding:

    •Doesn't work with properties on Freezables

    If you look at GeometryDrawing you can see its inheritance hierarchy includes Freezable: GeometryDrawing:Drawing:Animatable:Freezable:DependencyObject:DispatcherObject:Object

    So, you can't use a TemplateBinding on the Brush property of the Freezable GeometryDrawing.

    You can use the TemplateBinding on the Border's BorderBrush property because Border does not inherit from Freezable: Border:Decorator:FrameworkElement:UIElement:Visual:DependencyObject:DispatcherObject:Object