Question

As many WPFers, I use this pattern to create a vector icon:

1 - Defining a Canvas contains the data:

Resource Item:

<Canvas Width="256" Height="256" ClipToBounds="True" x:Key="SubmitVisualIcon">
    <Path Fill="#FFFFFF00">
        <Path.Data>
            <PathGeometry FillRule="Nonzero" Figures="M44.436129,25.256006L54.222273,25.256006 75.259996,46.29286 70.368799,51.187792 54.094614,67.462006 44.561911,67.462006 44.436129,67.337162 62.016504,49.752106 15.633995,49.752106 15.633995,42.837337 62.016504,42.837337z M45,5.6100006C23.245507,5.6100006 5.6100006,23.245506 5.6100006,45 5.6100006,66.754498 23.245507,84.389999 45,84.389999 66.754499,84.389999 84.389997,66.754498 84.389997,45 84.389997,23.245506 66.754499,5.6100006 45,5.6100006z M45,0C69.852816,0 89.999998,20.147187 89.999998,45 89.999998,69.852814 69.852816,90.000004 45,90.000004 20.147188,90.000004 9.5367432E-07,69.852814 0,45 9.5367432E-07,20.147187 20.147188,0 45,0z"/>
        </Path.Data>
    </Path>
</Canvas>

2 - Using it in a control template:

ControlTemplate:

<ControlTemplate x:Key="MyButton" TargetType="{x:Type Button}">
    <Border x:Name="root">
        <Grid>
            <Rectangle VerticalAlignment="Center" HorizontalAlignment="Center" 
                       RenderOptions.BitmapScalingMode="HighQuality"
                       Width="32" Height="32">
                <Rectangle.Fill>
                    <VisualBrush Stretch="Fill">
                        <VisualBrush.Visual>
                            <Binding Path="(ui:UIElement.VisualIcon)"
                                     RelativeSource="{RelativeSource TemplatedParent}"/>
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Rectangle.Fill>
            </Rectangle>
            <ContentPresenter />
        </Grid>
    </Border>
</ControlTemplate>

which the ui:UIElement.VisualIcon property, is an attached property to telling the template which resource to use. For example:

<Button Content="Save" ui:UIElement.VisualIcon="{DynamicResource SubmitVisualIcon}">

Now, as you can see, I have to get the Path in the Canvas a Fill value:

<Path Fill="#FFFFFF00">

The question is, is it possible to bind the Fill value to something on TemplatedParent? e.g. I have an attached property to holding icon brush:

<Button Content="Save" ui:UIElement.VisualIcon="{DynamicResource SubmitVisualIcon}"
                       ui:UIElement.VisualIconForeground="Some_Brush">

And I tried to use it like below:

<Path Fill="{Binding ui:UIElement.VisualIconForeground,RelativeSource={RelativeSource TemplatedParent}}">

But it doesn't work. Have you any idea to do this? I mean binding a resource item's some property to be set where they will be used? -Bad English, I know, sorry :(

Was it helpful?

Solution

Finally I found a solution that works in case. I should use Rectangle.OpacityMask instead of Rectangle.Fill:

The resource:

<Canvas Width="256" Height="256" ClipToBounds="True" x:Key="SubmitVisualIcon">
    <Path Fill="#FFFFFF00">
        <Path.Data>
            <PathGeometry FillRule="Nonzero" Figures="M44.436129,25.256006L54.222273,25.256006 75.259996,46.29286 70.368799,51.187792 54.094614,67.462006 44.561911,67.462006 44.436129,67.337162 62.016504,49.752106 15.633995,49.752106 15.633995,42.837337 62.016504,42.837337z M45,5.6100006C23.245507,5.6100006 5.6100006,23.245506 5.6100006,45 5.6100006,66.754498 23.245507,84.389999 45,84.389999 66.754499,84.389999 84.389997,66.754498 84.389997,45 84.389997,23.245506 66.754499,5.6100006 45,5.6100006z M45,0C69.852816,0 89.999998,20.147187 89.999998,45 89.999998,69.852814 69.852816,90.000004 45,90.000004 20.147188,90.000004 9.5367432E-07,69.852814 0,45 9.5367432E-07,20.147187 20.147188,0 45,0z"/>
        </Path.Data>
    </Path>
</Canvas>

The Template:

<ControlTemplate x:Key="MyButton" TargetType="{x:Type Button}">
    <Border x:Name="root">
        <Grid>
            <Rectangle VerticalAlignment="Center" HorizontalAlignment="Center" 
                       RenderOptions.BitmapScalingMode="HighQuality"
                       Width="32" Height="32"
                       Fill="{TemplateBinding ui:UIElement.VisualIconForeground}">
                <!-- fill the rectangle with what color do you want, it also can be bounded to every thing -->
                <!-- and then, use the Canvas as a OpacityMask on rectangle, just like this: -->
                <Rectangle.OpacityMask>
                    <VisualBrush Stretch="Fill">
                        <VisualBrush.Visual>
                            <Binding Path="(ui:UIElement.VisualIcon)"
                                     RelativeSource="{RelativeSource TemplatedParent}"/>
                        </VisualBrush.Visual>
                    </VisualBrush>
                </Rectangle.OpacityMask>
                <!-- this will show the icon with color you defined in Rectangle.Fill -->
            </Rectangle>
            <ContentPresenter />
        </Grid>
    </Border>
</ControlTemplate>

Usage:

<Button Content="Save" ui:UIElement.VisualIcon="{DynamicResource SubmitVisualIcon}"
                       ui:UIElement.VisualIconForeground="Some_Brush">

Another Usage:

<Button Content="Save" ui:UIElement.VisualIcon="{DynamicResource SubmitVisualIcon}"
                       ui:UIElement.VisualIconForeground="Some_Another_Brush">

Another Usage 2:

<Button Content="Save" ui:UIElement.VisualIcon="{DynamicResource AnotherVisualIcon}"
                       ui:UIElement.VisualIconForeground="Some_Another_Brush">

OTHER TIPS

Too long for comment, so I will write here:

If I understand correctly, SubmitVisualIcon is a Resource. Resource Binding does not support, so you do not work Binding with TemplatedParent, because the Resource is not part of the visual tree, or part of the template. Probably you'll have to look for an alternative.

As an alternative, you can use the settings that are supported by the application. Set the color in the settings, and reference it in the resource like that:

xmlns:properties="clr-namespace:MyNamespace.Properties"

<Path Fill="{Binding Source={x:Static properties:Settings.Default}, Path=SomeColor, Mode=TwoWay}" ... />

More information can be found here and here.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top