Search code examples
c#wpfxamlsystem.windows.mediacontrol-template

Changing color of the GeometryDrawing Brush when Button is pressed


I created a Button Template. There are an Image and a Label. The Source of the Image is in a ResourceDictionary Pictures. The Source of the picture is a DrawingImage with White brush color.

<DrawingImage x:Key="Moduly">
  <DrawingImage.Drawing>
    <DrawingGroup>
      <GeometryDrawing Brush="{Binding BackgroundColor}" Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z " />
      <GeometryDrawing Brush="{Binding IconColor}" Geometry="M800.336 949.171H184.527c-80.603 0-136.768-65.56-136.768-146.159V203.677  c0-80.602 56.166-152.42 136.768-152.42h615.809c80.598 0 149.289 71.818 149.289 152.42v599.334  C949.625 883.611 880.934 949.171 800.336 949.171L800.336 949.171z M874.488 203.677c0-39.184-34.99-77.287-74.152-77.287H184.527  c-39.166 0-61.632 38.103-61.632 77.287v599.334c0 39.182 22.466 71.024 61.632 71.024h615.809  c39.162 0 74.152-31.843 74.152-71.024V203.677L874.488 203.677z M273.604 613.832h447.829v75.134H273.604V613.832L273.604 613.832z   M273.604 463.566h447.829v75.131H273.604V463.566L273.604 463.566z M273.604 313.295h447.829v75.134H273.604V313.295  L273.604 313.295z" />                   
    </DrawingGroup>
  </DrawingImage.Drawing>     
</DrawingImage>

The source of all styles (Button, StackPanel, Label) is in resource dictionary Styles.

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
  <Style TargetType="Button">
    <Setter Property="BorderBrush" Value="Black"/>
    <Setter Property="Background" Value="#103255"/>
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="{x:Type Button}">
          <Border Background="{TemplateBinding Background}">
            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
          </Border>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
    <Style.Resources>        
      <Style TargetType="StackPanel">
        <Style.Resources>
          <Style TargetType="Label">
            <Setter Property="Foreground" Value="White" />
            <Style.Triggers>
              <DataTrigger Binding="{Binding IsPressed, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
                           Value="True">
                <Setter Property="Foreground" Value="#103255" />
              </DataTrigger>
            </Style.Triggers>
          </Style>                
        </Style.Resources>
      </Style>
    </Style.Resources>
    <Style.Triggers>
      <Trigger Property="IsMouseOver" Value="True">
        <Setter Property="Background" Value="#103255"/>
        <Setter Property="BorderBrush" Value="Black"/>                
      </Trigger>
      <Trigger Property="IsPressed" Value="True">
        <Setter Property="Background" Value="White"/>
        <Setter Property="BorderBrush" Value="White"/>
      </Trigger>
    </Style.Triggers>
  </Style>        
</ResourceDictionary>

I need to change the brush color of the DrawingImage when the button is pressed. Only the specific one picture inside the pressed button.

<Button Grid.Column="0" Grid.Row="2" Name="modulyButton"
        HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
        BorderThickness="3" Margin="0,0,0,0">
  <StackPanel Orientation="Vertical" Name="modulyStackPanel"
              HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <Image x:Name="modulyImage" Source="{StaticResource Moduly}"
           HorizontalAlignment="Stretch" VerticalAlignment="Stretch"
           Height="30" Width="30"/>
    <Label x:Name="modulyLabel" Content="MODULY"
           VerticalAlignment="Center"/>
  </StackPanel>
</Button>

Does anyone have a solution?


Solution

  • I think there is no way, with the structure you created. At compile time the Image of the Button knows only that a StaticResource of the correct type has been assigned to its Source property, but it doesn't know that the Source instance has a DrawingGroup with 2 elements which have a Brush property, and so there is no way to call that Brush property in the Image.Triggers. You have to substitute the whole DrawingImage.

    My solution (in a simplified form, with Green/Red color switch):

    1) Create two DrawingImage, with the same Geometry but different Brush:

    <DrawingImage x:Key="Moduly1">
      <DrawingImage.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="Green" Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z" />
        </DrawingGroup>
      </DrawingImage.Drawing>
    </DrawingImage>
    
    <DrawingImage x:Key="Moduly2">
      <DrawingImage.Drawing>
        <DrawingGroup>
          <GeometryDrawing Brush="Red" Geometry="M 0,0L 32,0L 32,32L 0,32L 0,0 Z" />
        </DrawingGroup>
      </DrawingImage.Drawing>
    </DrawingImage>
    

    2) In the Button Template (in the ResourceDictionary) write this on the inner StackPanel style:

    <Style TargetType="StackPanel">
      <Style.Resources>
        <Style TargetType="Label">
          <Setter Property="Foreground" Value="White" />
          <Style.Triggers>
            <DataTrigger Binding="{Binding IsPressed,
                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
                         Value="True">
              <Setter Property="Foreground" Value="#103255" />
            </DataTrigger>
          </Style.Triggers>
        </Style>
        <!-- ADDED PART -->
        <Style TargetType="Image">
          <Setter Property="Source" Value="{StaticResource ResourceKey=Moduly1}"/>
          <Style.Triggers>
            <DataTrigger Binding="{Binding IsPressed,
                            RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Button}}}"
                         Value="True">
              <Setter Property="Source" Value="{StaticResource ResourceKey=Moduly2}" />
            </DataTrigger>
          </Style.Triggers>
        </Style>
        <!-- END ADDED PART -->
      </Style.Resources>
    </Style>
    

    3) In the particular instance of you Button, remove the Source property from the Image element.