如何为多个鼠标悬停事件创建单一样式?

How to create a single style for multiple mouse over events?

我有四个按钮和四个文本框,其中每个按钮都 linked 到其中一个文本块。当鼠标悬停在按钮上时,我希望相应的文本块淡入(并在鼠标离开时淡出)。有很多这样的示例显示单个按钮和文本块,您可以在其中简单地将数据触发器绑定到文本块样式中的按钮名称。

这是我目前所获得的(所有这些都是文本块样式):

<DataTrigger Binding="{Binding ElementName=UpdateButton, Path=IsMouseOver}" Value="True">
    <DataTrigger.EnterActions>
         <BeginStoryboard>
              <Storyboard TargetProperty ="Opacity" Duration="00:00:01">
                   <DoubleAnimation From="0" To="1" Duration="00:00:01"/>
              </Storyboard>
         </BeginStoryboard>
    </DataTrigger.EnterActions>
    <DataTrigger.ExitActions>
         <BeginStoryboard>
              <Storyboard TargetProperty ="Opacity" Duration="00:00:01">
                   <DoubleAnimation From="1" To="0" Duration="00:00:01"/>
              </Storyboard>
         </BeginStoryboard>
    </DataTrigger.ExitActions>
</DataTrigger>

截至目前,当我将鼠标悬停在更新按钮上时,会显示所有文本块,而不仅仅是与更新按钮关联的文本块。

为了解决这个问题,我可以通过名称为每个文本块创建样式并绑定到适当的按钮,但这是大量的重复。我可能会使用 "BasedOn" 来分离按钮绑定,但是我们仍然在复制 Storyboard 等的所有代码。但是有人知道更好的方法吗?

似乎应该有一种方法可以使用单个通用绑定以单一样式创建这一切,但 link 文本块的特定按钮,因此该按钮仅触发情节提要,因为它是 linked 文本块。任何人都知道如何做到这一点,或者更好的方法?

处理此问题的一个好方法是创建一个可以存储对按钮的引用的自定义继承 TextBlock

例子

using System.Windows;
using System.Windows.Controls;

//Custom TextBlock
public class SpecialTextBlock : TextBlock
{
    //This will be the button reference
    public Button BoundButton { get; set; }

    //Register the BoundButton as a dependency to allow binding
    public static readonly DependencyProperty ButtonProperty = DependencyProperty.Register
    (
        "BoundButton",
        typeof(Button),
        typeof(SpecialTextBlock),
        new FrameworkPropertyMetadata(default(Button))
    );
}

现在您的新 SpecialTextBlock 已设置,您可以为其创建新样式。使用您原来的样式,但将其应用于 TargetType="local:SpecialTextBlock" 而不是 TargetType="TextBlock"

然后根据样式中的示例更新您的 DataTrigger,以便触发器绑定到自身(SpecialTextBlock),然后查看引用的 Button 路径。

<DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=BoundButton.IsMouseOver}" Value="True">
...

现在您已完成设置,可以像这样创建您的 TextBlocks,而无需重新设计样式。

//Set your BoundButton binding to specify which button triggers the animation.
<local:SpecialTextBlock BoundButton="{Binding ElementName=UpdateButton}" />
<StackPanel>
 <Button x:Name="MouseTarget"
     Content="Mouse Over This"
     />
 <Button Content="This one changes...">
  <Button.Style>
   <Style TargetType="Button">
    <Style.Triggers>
     <DataTrigger Binding="{Binding ElementName=MouseTarget, Path=IsMouseOver}" Value="True">
      <Setter Property="Background" Value="Red" />
     </DataTrigger>
    </Style.Triggers>
   </Style>
  </Button.Style>
 </Button>
</StackPanel>