Search code examples
c#.netwpf

How does one make a transparent portion of a button clickable in WPF?


I have a bunch of toolstrip buttons with transparent backgrounds in WPF. When the user mouses over the outside of the button, nothing happens, because that part of the button is transparent. Once the user mouses over one of the non-transparent areas of the button, the "hover" behavior changes the border and background color. The background is no longer transparent, so the hover behavior continues for a much larger area than before. I would like the transparent areas of the button to behave as if the button were non-transparent there.

That is, now I have this behavior where the button is unselected despite the mouse being clearly inside the button area:

Bad Behavior

and I'm trying to get the button to be selected like this even if the user has not previously moused over the foreground "white" part of the button:

Good Behavior

I tried setting IsHitTestVisible on the button itself, but that didn't seem to make any difference.

Is there a way to ask WPF to consider the transparent areas of the button significant?

XAML currently looks like this:

<Button Style="{StaticResource MainToolstripButtonStyle}" Margin="5,0,0,0"
ToolTip="{StaticResource OpenButtonText}"
AutomationProperties.Name="{StaticResource OpenButtonText}"
Command="{StaticResource Open}"
Content="{StaticResource OpenIcon}" />

<Style x:Key="MainToolstripButtonStyle" TargetType="Button">
    <Setter Property="Width" Value="24" />
    <Setter Property="Height" Value="24" />
    <Setter Property="Background" Value="{x:Null}" />
    <Setter Property="Foreground" Value="White" />
    <Setter Property="Padding" Value="0" />
    <!-- If users want to use keyboard navigation, they use the menu instead. -->
    <Setter Property="IsTabStop" Value="False" />
    <Setter Property="Focusable" Value="False"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Border Name="Border"
              BorderThickness="1"
              BorderBrush="{x:Null}">
                    <ContentPresenter HorizontalAlignment="Center"
                          VerticalAlignment="Center" 
                          RecognizesAccessKey="True" />
                </Border>
                <ControlTemplate.Triggers>
                    <!-- Low contrast triggers for selection / focus / enabled: -->
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Source={x:Static vvm:SystemParametersBindingTarget.Instance}, Path=HighContrast}" Value="False" />
                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsMouseOver}" Value="True" />
                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="True" />
                        </MultiDataTrigger.Conditions>
                        <Setter TargetName="Border"
                  Property="Background"
                  Value="{StaticResource HotToolbarButtonBrush}" />
                        <Setter TargetName="Border"
                  Property="BorderBrush"
                  Value="{StaticResource HotToolbarButtonBorderBrush}" />
                    </MultiDataTrigger>

                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding Source={x:Static vvm:SystemParametersBindingTarget.Instance}, Path=HighContrast}" Value="False" />
                            <Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False" />
                        </MultiDataTrigger.Conditions>
                        <Setter Property="Foreground"
                  Value="{StaticResource DisabledToolbarButtonBrush}" />
                    </MultiDataTrigger>

                    <!-- High contrast triggers omitted -->
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>  

Solution

  • Replace

    <Setter Property="Background" Value="{x:Null}" />
    

    by

    <Setter Property="Background" Value="Transparent" />
    

    and use the Background property in the ControlTemplate:

    <ControlTemplate TargetType="{x:Type Button}">
        <Border Name="Border" Background="{TemplateBinding Background}" ...>
            ...
        </Border>
    </ControlTemplate>