【问题标题】:Use style trigger to set property of a nested object使用样式触发器设置嵌套对象的属性
【发布时间】:2011-11-01 10:54:44
【问题描述】:

我在大画布上写了一个小多边形。当鼠标在画布上移动时,我想突出显示一个多边形。代码是这样的:

<UserControl ...>
  <Canvas Name="canvas" Height="22" Width="22">
      <Canvas.Resources>
          <Style TargetType="Canvas">
              <Style.Triggers>
                  <Trigger Property="IsMouseOver" Value="false">
                      <Setter Property="polygon.Stroke" Value="#EEEEEE"/>
                  </Trigger>
                  <Trigger Property="IsMouseOver" Value="true">
                    <Setter Property="polygon.Stroke" Value="Aqua"/>
                </Trigger>
              </Style.Triggers>
          </Style>
      </Canvas.Resources>
      <Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
              <Polygon.Fill>
                  <SolidColorBrush Color="#EEEEEE"/>
              </Polygon.Fill>
      </Polygon>
  </Canvas>
</UserControl>

但是 setter 看不到“多边形”。

【问题讨论】:

    标签: wpf xaml


    【解决方案1】:

    您不能像那样使用Setters,如果您使用这种表示法,引擎将查找附加属性,或者如果没有为点之前类型的属性设置Style.TargetType

    最简单的做法可能是将样式应用于多边形本身并使用绑定到CanvasDataTrigger,以便您可以触发其属性。

      <Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
           <Polygon.Fill>
               <SolidColorBrush Color="#EEEEEE"/>
           </Polygon.Fill>
           <Polygon.Style>
              <Style TargetType="{x:Type Polygon}">
                 <Style.Triggers> 
                    <DataTrigger
                       Binding="{Binding Path=IsMouseOver,
                                         RelativeSource={RelativeSource
                                         AncestorType={x:Type Canvas}}}"
                       Value="True">
                       <Setter Property="Stroke" Value="Red"/>
                    </DataTrigger>
                 </Style.Triggers>
              </Style>
           <Polygon.Style>
      </Polygon>
    

    【讨论】:

    • 它有效,但仍然只有当鼠标悬停在多边形上时,而不是在画布的其余部分上。 :(
    • @Badiboy:好吧,正如另一个答案所指出的,您需要在画布上设置背景,否则没有命中测试。
    • @AngelWPF:如果我大部分时间不添加故意的代码,可能会导致人们复制和粘贴而不是理解这个概念。例如,您的代码在绑定中使用RelativeSource,而还有其他方式,因此即使代码没有被复制,某个方法也会在通用概念上得到加强。
    • @H.B.,我认为正如您已经解释了答案,代码将帮助一个业余开发人员有更清晰的理解。例如,我曾经是我自己,当只是解释的时候,我很挣扎,因为这会让我更加困惑。再次抱歉编辑您的答案。如果需要,您可以将其删除。
    • @H.B.我为此用户控件替换了 HitTestCore,因此即使画布中没有背景,事件也会被调整。不过我会尝试设置背景...
    【解决方案2】:

    试试EventTrigger,因为其他类型的触发器只能在模板或样式中使用。而且我们已经知道 Style.Trigger 不允许您的方案。所以这里是你的工作示例:

    <Canvas Name="canvas" Height="22" Width="22">
        <Polygon Points="11,1 16,6 16,16 11,21" Name="polygon">
            <Polygon.Fill>
                <SolidColorBrush x:Name="brush" Color="#EEEEEE"/>
            </Polygon.Fill>
            <Polygon.Triggers>
                <EventTrigger RoutedEvent="UIElement.MouseEnter">
                    <BeginStoryboard>
                        <Storyboard Storyboard.TargetName="brush" Storyboard.TargetProperty="Color">
                            <ColorAnimation From="#EEEEEE" To="Aqua" Duration="00:00:00.01" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
                <EventTrigger RoutedEvent="UIElement.MouseLeave">
                    <BeginStoryboard>
                        <Storyboard Storyboard.TargetName="brush" Storyboard.TargetProperty="Color">
                            <ColorAnimation From="Aqua" To="#EEEEEE" Duration="00:00:00.01" />
                        </Storyboard>
                    </BeginStoryboard>
                </EventTrigger>
            </Polygon.Triggers>
        </Polygon>
    </Canvas>
    

    【讨论】:

    • 你可以用普通的触发器(Trigger.EnterActions & Trigger.ExitActions)做同样的事情,关键是这是一个不同的动画。此外,您的示例不再在画布上触发,而是在多边形本身上触发。
    • 对于 EnterActions/ExitActions,您需要一个属性 IsMouseOver,它是 IInputInterface 的一部分。但是 Canvas 和 Polygon 都没有实现。
    • Canvas 是透明的,所以路由事件 MouseEnter/MouseLeave 不会触发。您需要为其指定一些背景,至少几乎是透明的。
    • 似乎“RoutedEvent”仅在鼠标悬停在多边形上时才对多边形起作用,因为如果它们都在事件点下方,它会从父级路由到子级...
    • @invisible:示例中的canvas是透明的不是重点,Polygon和Canvas都有IsMouseOver,你在说什么?
    【解决方案3】:

    它正在寻找名为“多边形”的 Canvas 属性,而后者又具有一个名为“Stroke”的属性。如果您希望 setter 以不同的对象为目标,则需要使用 TargetName。

    <Setter TargetName="polygon" Property="Stroke" Value="#EEEEEE" />
    

    【讨论】:

    • 我试过这个。但是“无法在样式设置器上设置 TargetName 属性。”
    • 鸡蛋在脸上。我总是忘记那个小小的限制。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-27
    • 2014-02-22
    • 1970-01-01
    • 2021-07-10
    • 2019-04-18
    相关资源
    最近更新 更多