通过其他元素EventTrigger触发Storyboard动画时程序进入中断模式的原因
为什么触发动画会导致程序进入中断模式?
你碰到的这个问题,本质是WPF的命名作用域限制在搞鬼:DataTemplate有自己独立的命名空间,里面的EventTrigger根本找不到模板外面的grid1元素。当你触发鼠标点击事件时,Storyboard尝试访问一个不存在的目标,直接抛出异常,导致程序进入中断模式。
两种可行的解决方案
方案1:直接跨作用域绑定目标元素
把Storyboard.TargetName换成通过ElementName绑定的方式,这样就能跳过DataTemplate的命名限制,直接定位到外部的grid1:
<Grid Name="grid1" Height="100"/> <ItemsControl> <ItemsControl.ItemTemplate> <DataTemplate> <Grid> <Grid.Triggers> <EventTrigger RoutedEvent="Grid.MouseDown"> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.Target="{Binding ElementName=grid1, Mode=OneTime}" Storyboard.TargetProperty="Height" From="100" To="60" Duration="0:0:5"/> </Storyboard> </BeginStoryboard> </EventTrigger> </Grid.Triggers> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
这里的关键是用Storyboard.Target配合ElementName绑定,替代原来的Storyboard.TargetName——ElementName可以跨命名作用域找到同一个逻辑树里的元素。
方案2:用MVVM模式间接控制(更优雅)
如果你的项目遵循MVVM规范,推荐用绑定属性的方式,避免直接操作UI元素:
第一步:在ViewModel里定义属性和命令
// 记得实现INotifyPropertyChanged接口 private double _gridHeight = 100; public double GridHeight { get => _gridHeight; set { _gridHeight = value; OnPropertyChanged(nameof(GridHeight)); } } // 点击触发的命令 public ICommand TriggerHeightChangeCommand => new RelayCommand(() => { // 如果需要平滑动画,可以在这里添加Storyboard逻辑,或者用动画库 GridHeight = 60; });
第二步:修改XAML绑定
<Grid Height="{Binding GridHeight}"/> <ItemsControl> <ItemsControl.ItemTemplate> <DataTemplate> <Grid> <!-- 需要引用System.Windows.Interactivity程序集 --> <i:Interaction.Triggers> <i:EventTrigger EventName="MouseDown"> <i:InvokeCommandAction Command="{Binding DataContext.TriggerHeightChangeCommand, RelativeSource={RelativeSource AncestorType=ItemsControl}}"/> </i:EventTrigger> </i:Interaction.Triggers> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl>
这种方式彻底避开了命名作用域的问题,也更符合WPF的设计理念,维护起来更方便。
内容的提问来源于stack exchange,提问作者kolorowezworki
相关产品推荐
相关产品推荐

