Question

I want a button that is an ellipse with a centered 'x' that will change it's colours on mouse over (both the colour of the 'x' and that of the ellipse).

Similar to this enter image description here

The following gets the standard appearance I want

    <Grid>
    <Grid.Resources>
        <Style x:Key="CloseButtonBackgroundStyle" TargetType="{x:Type Ellipse}">
            <Setter Property="Width" Value="25" />
            <Setter Property="Height" Value="25" />
            <Setter Property="Fill" Value="#f4f4f4" />
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Fill" Value="Red" />
                </Trigger>
            </Style.Triggers>
        </Style>

        <Style x:Key="CloseButtonForegroundStyle" TargetType="{x:Type TextBlock}">
            <Setter Property="Foreground" Value="#898989" />
            <Setter Property="HorizontalAlignment" Value="Center" />
            <Setter Property="VerticalAlignment" Value="Center" />
            <Setter Property="FontSize" Value="16" />
            <Setter Property="Padding" Value="0 0 0 4" />

            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Foreground" Value="#f9ebeb" />
                </Trigger>
            </Style.Triggers>
        </Style>            
    </Grid.Resources>

    <Ellipse Style="{StaticResource CloseButtonBackgroundStyle}" />

    <TextBlock Text="x"
               Style="{StaticResource CloseButtonForegroundStyle}"/>
</Grid>

The trouble is using the IsMouseOver property. It does work but only for each control. i.e. when I'm over the ellipse the background turns red BUT when I then go over the textblock the ellipse is no longer mouse over and so it turns back to the standard fill colour.

Do I need to change my approach so that the content of the ellipse is the textblock?

Many thanks

Était-ce utile?

La solution

The issue is that the TextBlock actually covers more real estate than the 'x' because fonts have intrinsic padding around the pixels that form the letter. So the mouse could actually be over the TextBlock (and not just the pixels of the 'x' character) and this would prevent your other trigger from firing. This would account for the either/or effect you are experiencing.

Among other approaches, one possibility is to wrap both elements into a control template...

<Grid>
    <Grid.Resources>
        <ControlTemplate x:Key="EllipseWithText" TargetType="{x:Type Button}">
            <Grid x:Name="MainGrid">
                <Rectangle x:Name="MainRectangle" Fill="#00000000" RadiusX="5" RadiusY="5"/>
                <ContentPresenter x:Name="Presenter" 
                              HorizontalAlignment="Center"  VerticalAlignment="Center" 
                              TextBlock.Foreground="#BB225588"/>
                <Path x:Name="Cross" Data="M0,0 L1,1 M0,1 L1,0" 
                              Stretch="Fill" Stroke="Black" 
                              StrokeThickness="2" Width="8" Height="8" />
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="MainRectangle" Property="Fill" Value="Red"/>
                    <Setter TargetName="MainRectangle" Property="Stroke" Value="Transparent"/>
                    <Setter TargetName="Cross" Property="Stroke" Value="White" />
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Grid.Resources>
    <Button Height="15" Width="15" Template="{StaticResource EllipseWithText}"/>
</Grid>

This will give your desired effect of having the ellipse turn red and the 'x' turn a different colour. Note that this template does not use a TextBlock, but instead uses a Path. The Path simulates an 'x' character. This approach causes less real estate to collide and gives the effect you are after.

Autres conseils

I know I'm a little late with this but I was having the same issue now. I came to the conclusion that setting the IsHitTestVisible="False" on the TextBlock was a more easy solution to this problem.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top