开发者

A problem with using triggers in XAML

开发者 https://www.devze.com 2023-03-21 07:51 出处:网络
At the code below, when a mouse is over the grid, the grid\'s Background is expected to be red, but it isn\'t executed as expected.

At the code below, when a mouse is over the grid, the grid's Background is expected to be red, but it isn't executed as expected.

<Grid>
    <Grid.Style>
    <Style TargetType="{x:Type Grid}">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Red"/>
            </Trigger>
        </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

However, if I added the Setter to make the Background green, it would be executed properly.

<Grid>
    <Grid.Style>
    <Style TargetType="{x:Type Grid}">
        <Setter Property="Background" Value="Green"/><!-- at the former, added code-->
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Background" Value="Red"/>
            </Trigger>
        </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

I don't know why it is, but guess that there is a precedence for setting the Background, causing the issue. Here is Dependency Property Value Precedence from MSDN, and I understand the precedence of of that reference, but I cannot link this issue to the precedence(MSDN).

Additionally, at above the code snippets, if the Grid is replaced with a Button, both these code will not be executed as expected.


UPDATED: Adding Button case about this issue

<Button>
    <Button.Style >
        <Style TargetType="{x:Type Button}">
            <Setter Prop开发者_Go百科erty="Background"  Value="Transparent"/>
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>


The problem is your Grid has a null background, so it is not visible for mouse hit testing. If you set the Background to Transparent, then it will be hit-testable like when you set it to green.

More information can be found here.

I tried your Button and the Background is initialized to Transparent properly. The Red value is only shown for a fraction of a second. This is because in the Aero theme (I'm on Windows 7) the Button's ControlTemplate uses a custom chrome to provide animated state transitions (i.e. when hovering etc). This custom chrome element uses internal brushes and it ignores the Background property.

This has nothing to do with property precedence. For the Grid, it's simply a matter of your Grid not being hit-testable. So it's IsMouseOver will not be set to true, unless it has a non-null background (or a child which renders something).

You can see the Precedence in action here:

<Grid Background="Blue">
    <Grid.Style>
        <Style TargetType="{x:Type Grid}">
             <Setter Property="Background" Value="Green"/>
             <Style.Triggers>
                  <Trigger Property="IsMouseOver" Value="True">
                       <Setter Property="Background" Value="Red"/>
                  </Trigger>
              </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

In the above, the Grid will always be Blue as that has the highest precedence (i.e. local or #3). While Red (#6) takes precedence over Green (#8).

In the case of the Button, you have something like this:

<Button Background="Blue">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
             <Setter Property="Template">
                 <Setter.Value>
                     <ControlTemplate TargetType="Button">
                         <Border x:Name="border" Background="{TemplateBinding Background}">
                             <ContentPresenter />
                         </Border >
                         <ControlTemplate.Triggers>
                             <Trigger Property="IsMouseOver" Value="True">
                                 <Setter TargetName="border" Property="Background" Value="Red"/>
                             </Trigger>
                         </ControlTemplate.Triggers>
                     </ControlTemplate>
                 </Setter.Value>
              </Setter>
        </Style>
    </Button.Style>
</Button>

In this case, there are two Background properties in play: the Button and the Border in the control template. The Button's Background property is used by the Border by default, but when the mouse is hovering it uses a Red brush. At that point, it doesn't matter what the value of the Button's Background property is set to.

0

精彩评论

暂无评论...
验证码 换一张
取 消