如何使用选项卡项的 WPF 触发器为鼠标悬停事件设置动画?

发布于 2024-08-10 20:56:24 字数 3090 浏览 8 评论 0原文

我已经覆盖 tabitem 模板并创建了我自己的自定义样式。但是,我不确定如何为鼠标悬停事件编写事件触发器。


抱歉回复晚了,我没有收到评论通知(也许应该更改?)。 好的,我会尝试进一步解释这一点。我不添加评论,因为我需要发布示例代码。 假设您有一个控件,任何控件。 假设您还定义了许多画笔作为资源。 所以:

<LinearGradientBrush x:Key="NormalGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="NormalForeground">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Gray" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Red" Offset="0" />
    <GradientStop Color="Green" Offset="0.2" />
    <GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>

<RadialGradientBrush x:Key="MouseOverForeground" GradientOrigin="0.3,0.5">
    <GradientStop Color="Gray" Offset="0" />
    <GradientStop Color="Black" Offset="1" />
</RadialGradientBrush >

现在假设您有选项卡项控件:

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<Style x:Key="StyleTabItem"
       TargetType="{x:Type TabItem}">
    <Setter Property="Foreground"
            Value="{StaticResource NormalForeground}" />
    <Setter Property="BorderBrush"
            Value="Black" />
    <Setter Property="Background"
            Value="{StaticResource NormalGradientBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="Bd"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="1,1,1,0"
                            Padding="{TemplateBinding Padding}">
                        <ContentPresenter x:Name="Content"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        SnapsToDevicePixels="True"
                        ContentSource="Header"
                        RecognizesAccessKey="True" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver"
                             Value="true">
                        // what here?
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

所以问题是,我如何告诉 wpf 在 MouseOver 事件上执行从当前画笔到 MouseOverGradientBrush 以及从当前前景到 MouseOverForeground 的 3 秒动画? 我在示例中看到,您可以通过一一改变渐变的偏移量来做到这一点。我现在确实想要那个。它增加了代码的大小并且最终可能变得非常混乱。此外,画笔可能有不同数量的偏移,或者一个可以是线性的,另一个可以是径向的。 我希望这更清楚。

I have overriden tabitem template and created my own custom style. however, I'm not sure how to write event triggers for mouse over event.


Sorry for the late response, I am not getting a notification for comments (maybe this should be changed?).
Ok, i will try to explain this further. I am not adding comment because i need to post example code.
Let's say you have a control, any control.
Let's say you have also defined a number of brushes as resources.
So:

<LinearGradientBrush x:Key="NormalGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="NormalForeground">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Gray" Offset="1" />
</LinearGradientBrush>

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Red" Offset="0" />
    <GradientStop Color="Green" Offset="0.2" />
    <GradientStop Color="Black" Offset="1" />
</LinearGradientBrush>

<RadialGradientBrush x:Key="MouseOverForeground" GradientOrigin="0.3,0.5">
    <GradientStop Color="Gray" Offset="0" />
    <GradientStop Color="Black" Offset="1" />
</RadialGradientBrush >

Now let's say you have the tab item control:

<LinearGradientBrush x:Key="MouseOverGradientBrush">
    <GradientStop Color="Black" Offset="0" />
    <GradientStop Color="Red" Offset="1" />
</LinearGradientBrush>

<Style x:Key="StyleTabItem"
       TargetType="{x:Type TabItem}">
    <Setter Property="Foreground"
            Value="{StaticResource NormalForeground}" />
    <Setter Property="BorderBrush"
            Value="Black" />
    <Setter Property="Background"
            Value="{StaticResource NormalGradientBrush}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="Bd"
                            Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="1,1,1,0"
                            Padding="{TemplateBinding Padding}">
                        <ContentPresenter x:Name="Content"
                        HorizontalAlignment="Center"
                        VerticalAlignment="Center"
                        SnapsToDevicePixels="True"
                        ContentSource="Header"
                        RecognizesAccessKey="True" />
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver"
                             Value="true">
                        // what here?
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

So the question is, how can i tell wpf to do a 3 second animation from the current brush to MouseOverGradientBrush and from the current foreground to MouseOverForeground on the MouseOver Event?
I have seen in examples that you do that by changing offsets of gradient one by one. I do now want that. It increases the size of code and can end up being very messy. Besides brushes might have different number of offsets or one can be linear and the other one radial.
I hope this is clearer.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

云归处 2024-08-17 20:56:24

这应该有效。我拿出了一堆你必须帮助简化事情的触发器。如果您可以正常工作并需要添加更多功能,请告诉我,我们可以从那里开始构建它。

我还用静态颜色替换了您的资源引用。如果您将它们更改回资源并且它停止工作,那么这是您的资源所在位置的问题。

<LinearGradientBrush x:Key="MouseOverGradientBrush">
        <GradientStop Color="Black" Offset="0" />
        <GradientStop Color="Red" Offset="1" />
    </LinearGradientBrush>

 <Style x:Key="StyleTabItem"
           TargetType="{x:Type TabItem}">
        <Setter Property="Foreground"
                Value="{DynamicResource ForegroundGradient}" />
        <Setter Property="BorderBrush"
                Value="Black" />
        <Setter Property="Background"
                Value="Yellow" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid SnapsToDevicePixels="true">
                        <Border x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="1,1,1,0"
                                Padding="{TemplateBinding Padding}"
                                CornerRadius="2,2,2,2">
                            <ContentPresenter x:Name="Content"
                                              HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              ContentSource="Header"
                                              RecognizesAccessKey="True" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="{StaticResource MouseOverGradientBrush}" />
                        </Trigger>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Panel.ZIndex"
                                    Value="1" />
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="Cyan" />
                            <Setter Property="BorderBrush"
                                    TargetName="Bd"
                                    Value="Pink" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

This should work. I pulled out a bunch of the triggers you had to help simplify things. If you get this working and need to add more features let me know and we can build it out from there.

I also replaced your Resource references with static colors. If you change them back to resources and it stops working then it is an issue with where your resources are at.

<LinearGradientBrush x:Key="MouseOverGradientBrush">
        <GradientStop Color="Black" Offset="0" />
        <GradientStop Color="Red" Offset="1" />
    </LinearGradientBrush>

 <Style x:Key="StyleTabItem"
           TargetType="{x:Type TabItem}">
        <Setter Property="Foreground"
                Value="{DynamicResource ForegroundGradient}" />
        <Setter Property="BorderBrush"
                Value="Black" />
        <Setter Property="Background"
                Value="Yellow" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type TabItem}">
                    <Grid SnapsToDevicePixels="true">
                        <Border x:Name="Bd"
                                Background="{TemplateBinding Background}"
                                BorderBrush="{TemplateBinding BorderBrush}"
                                BorderThickness="1,1,1,0"
                                Padding="{TemplateBinding Padding}"
                                CornerRadius="2,2,2,2">
                            <ContentPresenter x:Name="Content"
                                              HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
                                              SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                              ContentSource="Header"
                                              RecognizesAccessKey="True" />
                        </Border>
                    </Grid>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsMouseOver"
                                 Value="true">
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="{StaticResource MouseOverGradientBrush}" />
                        </Trigger>
                        <Trigger Property="IsSelected"
                                 Value="true">
                            <Setter Property="Panel.ZIndex"
                                    Value="1" />
                            <Setter Property="Background"
                                    TargetName="Bd"
                                    Value="Cyan" />
                            <Setter Property="BorderBrush"
                                    TargetName="Bd"
                                    Value="Pink" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
世界和平 2024-08-17 20:56:24

使用事件触发器的最佳解决方案是使用 Expression Blend。它提供了一种直观的方式来创建触发器。

The best solution for using event triggers is to use Expression Blend. It comes with an intuitive way to create triggers.

何时共饮酒 2024-08-17 20:56:24

感谢您的所有回复。我的触发器工作正常。我只是无法让它们动起来。我有一个更简单的方法可以使用 VisualStateManager 在 silverlight 中执行此操作,但我不确定在 WPF 中如何完成此操作。

我提供了我的示例,因为表达式混合生成了 tabitem 的模板副本。

    <Style x:Key="StyleTabItem" TargetType="{x:Type TabItem}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusStyle}"/>
    <Setter Property="Foreground" Value="{DynamicResource ForegroundGradient}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TabItemGradientBrushUnselected}"/>
    <Setter Property="Background" Value="{StaticResource TabItemBorderBrushUnselected}"/>
    <Setter Property="Padding" Value="6,1,6,1"/>  
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="Storyboard1">
                        <DoubleAnimation
                                Storyboard.TargetName="Bd" 
                                Storyboard.TargetProperty="BorderBrush.GradientStops[0].Offset"
                                Duration="00:00:00.3"/>
                    </Storyboard>
                </ControlTemplate.Resources>
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="Bd" 
                    Background="{TemplateBinding Background}" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="1,1,1,0" 
                    Padding="{TemplateBinding Padding}"
                    CornerRadius="2,2,2,2">
                        <ContentPresenter x:Name="Content" 
                        HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
                        VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                        ContentSource="Header" 
                        RecognizesAccessKey="True"/>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                        </Trigger.EnterActions>
                        <Setter Property="Background" TargetName="Bd" Value="{StaticResource MouseOverGradientBrush}"/>
                    </Trigger>
                    <Trigger Property="Selector.IsSelected" Value="False"/>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Panel.ZIndex" Value="1"/>
                        <Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemGradientBrushSelected}"/>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemBorderBrushSelected}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="false"/>
                            <Condition Property="IsMouseOver" Value="true"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemMouseOverGradientBorder}"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="TabStripPlacement" Value="Top"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Margin" Value="-2,0,-2,0"/>
                        <Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource DisabledGradientBrush}"/>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource DisabledGradientBorder}"/>
                        <Setter Property="Foreground" Value="{DynamicResource DisabledForeground}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

我只想做的(首先)是在鼠标悬停时将 bd 的背景从当前值(无论是什么)更改为我在 mouseover=true 触发器(MouseOverGradientBrush)中拥有的值。上面的代码有什么问题并且动画不起作用?我已经尽我所能使用了表情混合...

Thanks for all your respones. My triggers work fine. I just cant animate them. I had a simpler wat to do this in silverlight by using VisualStateManager and I am not sure how this is done in WPF.

I am providing my sample, as expression blend generated the copy of the template for a tabitem.

    <Style x:Key="StyleTabItem" TargetType="{x:Type TabItem}">
    <Setter Property="FocusVisualStyle" Value="{StaticResource TabItemFocusStyle}"/>
    <Setter Property="Foreground" Value="{DynamicResource ForegroundGradient}"/>
    <Setter Property="BorderBrush" Value="{StaticResource TabItemGradientBrushUnselected}"/>
    <Setter Property="Background" Value="{StaticResource TabItemBorderBrushUnselected}"/>
    <Setter Property="Padding" Value="6,1,6,1"/>  
    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
    <Setter Property="VerticalContentAlignment" Value="Stretch"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabItem}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="Storyboard1">
                        <DoubleAnimation
                                Storyboard.TargetName="Bd" 
                                Storyboard.TargetProperty="BorderBrush.GradientStops[0].Offset"
                                Duration="00:00:00.3"/>
                    </Storyboard>
                </ControlTemplate.Resources>
                <Grid SnapsToDevicePixels="true">
                    <Border x:Name="Bd" 
                    Background="{TemplateBinding Background}" 
                    BorderBrush="{TemplateBinding BorderBrush}" 
                    BorderThickness="1,1,1,0" 
                    Padding="{TemplateBinding Padding}"
                    CornerRadius="2,2,2,2">
                        <ContentPresenter x:Name="Content" 
                        HorizontalAlignment="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
                        VerticalAlignment="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}" 
                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                        ContentSource="Header" 
                        RecognizesAccessKey="True"/>
                    </Border>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="true">
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource Storyboard1}"/>
                        </Trigger.EnterActions>
                        <Setter Property="Background" TargetName="Bd" Value="{StaticResource MouseOverGradientBrush}"/>
                    </Trigger>
                    <Trigger Property="Selector.IsSelected" Value="False"/>
                    <Trigger Property="IsSelected" Value="true">
                        <Setter Property="Panel.ZIndex" Value="1"/>
                        <Setter Property="Background" TargetName="Bd" Value="{StaticResource TabItemGradientBrushSelected}"/>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemBorderBrushSelected}"/>
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="false"/>
                            <Condition Property="IsMouseOver" Value="true"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource TabItemMouseOverGradientBorder}"/>
                    </MultiTrigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="IsSelected" Value="true"/>
                            <Condition Property="TabStripPlacement" Value="Top"/>
                        </MultiTrigger.Conditions>
                        <Setter Property="Margin" Value="-2,0,-2,0"/>
                        <Setter Property="Margin" TargetName="Content" Value="0,0,0,1"/>
                    </MultiTrigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter Property="Background" TargetName="Bd" Value="{DynamicResource DisabledGradientBrush}"/>
                        <Setter Property="BorderBrush" TargetName="Bd" Value="{DynamicResource DisabledGradientBorder}"/>
                        <Setter Property="Foreground" Value="{DynamicResource DisabledForeground}"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

What i simply want to do (for a start) is on mouseover to change bd's background from the current value (whatever that is) to the value i have in the mouseover=true trigger (MouseOverGradientBrush). What is wrong in the above code and the animation doesnt work? I have used expression blend all i could...

花开雨落又逢春i 2024-08-17 20:56:24

如果您确实想使用 EventTrigger,则可以这样做

<Style x:TargetType="TabItem">
    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseOver">
          <BeginStoryboard>
            ....
          </BeinStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

在大多数情况下,如果我正在进行简单、离散的值更改,我将在 IsMouseOver 属性更改时触发的属性触发器中执行此操作,而不是需要使用 EventTrigger动画

<Trigger Property="IsMouseOver" Value="True">
    <Setter Property="Foo" Value="Bar" />
</Trigger>

If you truly want to use an EventTrigger you can do so like this

<Style x:TargetType="TabItem">
    <Style.Triggers>
        <EventTrigger RoutedEvent="MouseOver">
          <BeginStoryboard>
            ....
          </BeinStoryboard>
        </EventTrigger>
    </Style.Triggers>
</Style>

In most cases If I am doing simple, discrete, value changes I will do it in a Property trigger that fires when the IsMouseOver property changes, as opposed to an EventTrigger which requires an animation

<Trigger Property="IsMouseOver" Value="True">
    <Setter Property="Foo" Value="Bar" />
</Trigger>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文