Search code examples
c#wpfcontentpresenter

ContentPresenter loads resource only first occurence [WPF]


I have WPF view, where I use buttons with style that I created by myself. In this style I use some icon from resources, that I pass by TemplateBinding. Unfortunately I faced strange problem: the resource is shown only at first occurrence of button with this style. In next buttons I have empty box.

Style:

<Style x:Key="TransparentStyle" TargetType="{x:Type Button}">
<Setter Property="BorderBrush" Value="LightSlateGray"/>
<Setter Property="Template">
    <Setter.Value>
        <ControlTemplate>
            <Grid>
                <Rectangle Width="13" Height="15"  x:Name="IconBrush">
                    <Rectangle.Fill>
                        <SolidColorBrush Color="DarkGray"></SolidColorBrush>
                    </Rectangle.Fill>
                    <Rectangle.OpacityMask>
                        <VisualBrush Stretch="Fill">
                            <VisualBrush.Visual>
                                <ContentPresenter Content="{TemplateBinding Button.Content}" />
                            </VisualBrush.Visual>
                        </VisualBrush>
                    </Rectangle.OpacityMask>
                </Rectangle>
            </Grid>
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="Mouse.MouseEnter">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="IconBrush"
                                            Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)"
                                            To="Black" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="Mouse.MouseLeave">
                    <BeginStoryboard>
                        <Storyboard>
                            <ColorAnimation Duration="0:0:0.1" Storyboard.TargetName="IconBrush" 
                                            Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)"
                                            To="DarkGray" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Setter.Value>
</Setter>
</Style>

Usege:

<WrapPanel Grid.Column="2" Margin="20 0">
    <Button Height="35" Width="35" Margin="3 3" Content="{StaticResource trash}" Style ="{StaticResource TransparentStyle}"/>
    <Button Height="35" Width="35" Margin="3 3" Content="{StaticResource trash}"  Style ="{StaticResource TransparentStyle}" />
</WrapPanel>

What is interesting, when I use another resources, they work at their first occurrences. So if I use another_res instead of trash, it works at first time.

How do I fix it?

EDIT:

Next tests show, that when I use any resource in style and problem repeats:

<VisualBrush.Visual>
    <ContentPresenter Content="{DynamicResource some_resource}" />
</VisualBrush.Visual>

EDIT2: The resource is defined in external source:

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="/Resources/Icons.xaml" />
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Window.Resources>

As canvas:

<Canvas x:Key="trash" Width="24" Height="24">
    <Path Data="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" Fill="Black" />
</Canvas>


Solution

  • Don't define your Icons like(I hope this is your problem as this is what people usually do, and Image is a FrameworkElement):

     <Image Source="Resources/SOF.gif" x:Key="trash"/>
    

    Define them like:

    <ImageBrush ImageSource="Resources/SOF.gif" x:Key="trash"/>
    

    and use ImageBrush like(in your style):

     <Rectangle Width="113" Height="95"  x:Name="IconBrush" Fill="{Binding RelativeSource={RelativeSource Mode=TemplatedParent},Path=Content}"/>
    

    your Icons will be repeated on buttons like below:

    Image

    Update:

    try it like:

    <VisualBrush x:Key="trash" >
            <VisualBrush.Visual>
                <Canvas  Width="24" Height="24" >
                    <Path Data="M19,4H15.5L14.5,3H9.5L8.5,4H5V6H19M6,19A2,2 0 0,0 8,21H16A2,2 0 0,0 18,19V7H6V19Z" Fill="Black" />
                </Canvas>
            </VisualBrush.Visual>
        </VisualBrush>
    

    OutPut:(make sure to use Rectangle fill correctly as I have mentioned above)

    buttons