WPF事件触发器更改其他UI元素

5

我在XAML中定义了ListBox,其中使用了ItemTemplate。 在ItemTemplate中,我放置了图像。

<ListBox.ItemTemplate>
<ListBox.ItemsPanel>
 <ItemsPanelTemplate>
  <WrapPanel x:Name="itmTempPanel" IsItemsHost="True" ItemWidth="60" ItemHeight="60" Width="{Binding ElementName=lstFilesDropped, Path=Width}"/>
 </ItemsPanelTemplate>
</ListBox.ItemsPanel>
...
<Image>
 <Image.Triggers>
  <EventTrigger RoutedEvent="MouseEnter">
   <BeginStoryboard>
    <Storyboard>
     <DoubleAnimation Storyboard.TargetProperty="Height" To="71" Duration="0:0:0.3" />
     <DoubleAnimation Storyboard.TargetName="itmTempPanel" Storyboard.TargetProperty="Height" To="71"      Duration="0:0:0.3" />
    </Storyboard>
   </BeginStoryboard>
  </EventTrigger>
 </Image.Triggers>
</Image>
</ListBox.ItemTemplate>

当鼠标进入图片时,我希望开始在该图片高度和我在ItemsPanelTemplate中定义的WrapPanel上进行故事板动画。但是当鼠标进入该图片时,我遇到了以下异常:“‘itmTempPanel’名称在‘System.Windows.Controls.Image’的命名范围内找不到。” 我该如何从开始故事板的元素更改其他元素属性呢?谢谢您的帮助!
1个回答

6
有两种方法可以解决这个问题。第一种是使用 .NET 4.0 中针对 WPF 的特性 {x:Reference}。如果你的应用程序目标是 .NET 4.0,那么你应该采用这种方法。这个想法是将 Storyboard.Target 设置为你想要动画的对象(在这种情况下是 WrapPanel)。虽然我们可以使用 Binding 来设置 Storyboard.Target,但我们不能使用 RelativeSourceElementName 来设置绑定源,因为 Storyboard(或 Timeline)不是 FrameworkElement(或 FrameworkContentElement)。唯一指定源的方法是设置 Source 属性。然而,我们通常可以将其设置为 StaticResourceDynamicResource 或直接设置(使用元素语法)。幸运的是,在 .NET 4.0 中引入了 {x:Reference},这可以帮助您引用 XAML 内部的任何命名对象(它的工作方式不像 ElementName)。以下是第一种方法的代码:
<DoubleAnimation Storyboard.Target="{Binding Source={x:Reference itmTempPanel}}" 
                 Storyboard.TargetProperty="Height" 
                 To="71" Duration="0:0:0.3" />    

第二种方法基于 DataTrigger。然而,该触发器不适用于 Image,而是适用于 WrapPanel。但现在可以使用 ElementName 将 Trigger 源绑定到 Image。因此,在不支持 {x:Reference} 的情况下,可以使用此方法。
<WrapPanel x:Name="itmTempPanel" IsItemsHost="True" ItemWidth="60" ItemHeight="60" 
           Width="{Binding ElementName=lstFilesDropped, Path=Width}">
  <WrapPanel.Style>
     <Style TargetType="WrapPanel">
        <Style.Triggers>
           <DataTrigger Binding="{Binding IsMouseOver,ElementName=image}" 
                        Value="True">
               <DataTrigger.EnterActions>
                 <BeginStoryboard>
                   <Storyboard>
                     <DoubleAnimation Storyboard.TargetProperty="Height" 
                                      To="71"  Duration="0:0:0.3" />
                   </Storyboard>
                 </BeginStoryboard>
               </DataTrigger.EnterActions>
           </DataTrigger>
        </Style.Triggers>
     </Style>
  </WrapPanel.Style>
</WrapPanel>

<Image Name="image">
  <Image.Triggers>
    <EventTrigger RoutedEvent="MouseEnter">
      <BeginStoryboard>
        <Storyboard>
           <DoubleAnimation Storyboard.TargetProperty="Height" To="71"
                            Duration="0:0:0.3" />     
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Image.Triggers>
</Image>

请注意,您需要为Image指定一个名称(例如image)。我们删除了WrapPanel的<DoubleAnimation>。不再使用EventTrigger,而是使用DataTrigger监听IsMouseOver属性。您还可以指定DataTrigger.ExitActions,以在IsMouseOver为false(等于MouseLeave)时开始动画。

2
哇,非常感谢!我非常感激这个,这非常帮助我,最终理解了如何仅通过XAML管理动画。再次感谢! - Jacob
3
更正一下,x:Reference 是在 .Net 4.0 中引入的,而不是 .Net 4.5。 - Rohit Vats
还有微软官方文档介绍如何从子事件动画父级吗?如果没有 Stack Overflow,该如何学习这个呢? - IronHide

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接