Search code examples
wpfxamlbuttonmouseoverstackpanel

How do I create an button that changes the source image AND the color of the text in a StackPanel in WPF?


In my WPF web app I have an image and a textblock inside of a stack panel, making a button. I have it set up so that if I mouseOver the image, it changes the source of the image so that another image appears(same image, but grayed-out). Also, if you mouseOver the textblock the text color changes from black to gray. How do I get both of these things to happen at once if the mouse rolls over either, or over the StackPanel that houses the items? My code:

<StackPanel x:Name="IntegrationRequestLinkStackPanel">
    <Button x:Name="IntegrationRequestLinkButton" Content="Integration Request">
         <Button.Template>
             <ControlTemplate>
                 <Image>
                     <Image.Style>
                         <Style TargetType="{x:Type Image}">
                             <Setter Propery="Source" Value+"Images/requestNew.png" />
                             <Setter Property="Cursor" Value="Hand" />
                             <Style.Triggers>
                                 <Trigger Property="IsMouseOver" Value="True">
                                     <Setter Property="Source" Value="Images"requestNewBW.png" />
                                 </Trigger>
                             </Style.Trigger>
                          </Style>
                      </Image.Style>
                  </Image>
             </ControlTemplate>
         </Button>
      </Button>
      <Textblock Text="Integration Request"............

The code for the Textblock is pretty much the same as for the button. Really I want the whole stack panel to be the button and when mouseOver the image inside changes and the text changes color.


Solution

  • The way you describe it, you want a button with an image and label as its content. You can place both in the template.

    <Button x:Name="IntegrationRequestLinkButton"
            Content="Integration Request">
      <Button.Style>
        <Style TargetType="Button">
          <Setter Property="Foreground" Value="Black" />
          <Setter Property="Cursor" Value="Hand" />
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="Button">
                <DockPanel LastChildFill="True">
                  <Image x:Name="Icon" 
                         DockPanel.Dock="Left"
                         Stretch="None"
                         Margin="0,0,5,0"
                         HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                         VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                         Source="Images/requestNew.png" />
                  <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                    VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </DockPanel>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="Icon"
                            Property="Source"
                            Value="Images/requestNewBW.png" />
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>            
            </Setter.Value>
          </Setter>
          <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
              <Setter Property="Foreground" Value="Gray" />
            </Trigger>          
          </Style.Triggers>
        </Style>
      </Button.Style>
    </Button>
    

    Typically, one adjusts inherited properties which apply to the entire control (like Foreground) using triggers on the Style as opposed to the Template. Use template triggers when you need to change a specific element defined by your template.

    As a matter of style, it seems odd that you would want to show black text and a color image by default, and gray text and a grayscale image on mouse-over. I would expect you to want the opposite.