【问题标题】:WPF: how to fire an EventTrigger (or Animation) when binding changes?WPF:绑定更改时如何触发 EventTrigger(或动画)?
【发布时间】:2010-12-18 09:40:30
【问题描述】:

我们有一个简单的动画,当检查并取消选中ToggleButton时运行(展开ListView的高度,然后折叠ListView的高度)。当以下 XAML 中 x:Name="DetailsGrid" 网格中的 DataContext 绑定发生变化时,如何为 <Storyboard x:Key="CommentsCollapse"> 触发 EventTrigger(或动画)?

换句话说,每当“DetailsGrid”的 Binding 发生变化时,我们都希望触发“CommentsCollapse” StoryBoard 以确保 ListView 返回到其折叠状态。

<Page
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Width="800"
   Height="400">
   <Page.Resources>
      <Storyboard x:Key="CommentsExpand">
         <DoubleAnimationUsingKeyFrames
            BeginTime="00:00:00"
            Storyboard.TargetName="CommentsListView"
            Storyboard.TargetProperty="(FrameworkElement.Height)">
            <SplineDoubleKeyFrame KeyTime="00:00:00.200" Value="300"/>
         </DoubleAnimationUsingKeyFrames>
      </Storyboard>
      <Storyboard x:Key="CommentsCollapse">
         <DoubleAnimationUsingKeyFrames
            BeginTime="00:00:00"
            Storyboard.TargetName="CommentsListView"
            Storyboard.TargetProperty="(FrameworkElement.Height)">
            <SplineDoubleKeyFrame KeyTime="00:00:00.200" Value="75"/>
         </DoubleAnimationUsingKeyFrames>
      </Storyboard>
   </Page.Resources>
   <Page.Triggers>
      <EventTrigger RoutedEvent="ToggleButton.Checked" SourceName="CommentsToggleButton">
         <BeginStoryboard Storyboard="{StaticResource CommentsExpand}"/>
      </EventTrigger>
      <EventTrigger RoutedEvent="ToggleButton.Unchecked" SourceName="CommentsToggleButton">
         <BeginStoryboard Storyboard="{StaticResource CommentsCollapse}"/>
      </EventTrigger>
   </Page.Triggers>
   <Grid DataContext="{Binding Path=CurrentTask.Workflow.Invoice}" x:Name="DetailsGrid">
      <StackPanel Orientation="Horizontal">
         <Canvas Width="428">
            <GroupBox Width="422" Margin="5,0,0,0">
               <GroupBox.Header>
                  <StackPanel Orientation="Horizontal">
                     <ToggleButton
                        x:Name="CommentsToggleButton"
                        Width="20"
                        Height="10"
                        Margin="5,0,0,0">
                        <ToggleButton.Content>
                           <Rectangle
                              Width="5"
                              Height="5"
                              Fill="Red"/>
                        </ToggleButton.Content>
                     </ToggleButton>
                     <TextBlock Foreground="Blue" Text="Comments"/>
                  </StackPanel>
               </GroupBox.Header>
               <ListView
                  x:Name="CommentsListView"
                  Height="75"
                  ItemsSource="{Binding Path=Comments}">
                  <ListView.View>
                     <GridView>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=Date}" Header="Date"/>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=Name}" Header="User"/>
                        <GridViewColumn DisplayMemberBinding="{Binding Path=Description}" Header="Comment"/>
                     </GridView>
                  </ListView.View>
               </ListView>
            </GroupBox>
         </Canvas>
      </StackPanel>
   </Grid>
</Page>

【问题讨论】:

    标签: wpf data-binding storyboard eventtrigger


    【解决方案1】:

    我认为你不能通过纯 Xaml 来做到这一点,你必须在代码中做到这一点(或者更好的是,编写一个通用的表达式行为,以便你可以用Xml)。查看 Dependency Property 的 PropertyMetadata,了解如何挂钩其 Property Changed 事件。

    【讨论】:

    • @Paul,您是否有任何资源(链接)可以指出我的方向?
    【解决方案2】:

    我也发现这在 XAML 中是不可能的。您需要 DataContextChanged 事件,它不是 RoutedEvent,因此不能在 EventTrigger 中使用。

    这似乎可行:

    <Window x:Class="DatacontextChangedSpike.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="300" Width="300">
        <Window.Resources>
            <Storyboard x:Key="ListViewExpands" AutoReverse="True" RepeatBehavior="2x">
                <DoubleAnimation Storyboard.TargetName="PulsingListView" Storyboard.TargetProperty="Height"
                                From="10" To="60"/>
            </Storyboard>
        </Window.Resources>
        <StackPanel>
            <ListView Name="PulsingListView" BorderThickness="2" BorderBrush="Black"
                      DataContextChanged="PulsingListView_DataContextChanged">
                <TextBlock>Listview</TextBlock>
            </ListView>
            <Button Click="Button_Click" >Change DataContext</Button>
        </StackPanel>
    </Window>
    
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Media.Animation;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace DatacontextChangedSpike
    {
        public partial class Window1 : Window
        {
            public Window1()
            {
                DataContext = new List<string>();
                InitializeComponent();
            }
    
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                DataContext = new List<int>();
            }
    
            private void PulsingListView_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
            {
                var sb = (Storyboard)FindResource("ListViewExpands");
                sb.Begin();
            }
        }
    }
    

    【讨论】:

    • @Dabblernl - 我们最初尝试过这个,但希望有一个纯 XAML 解决方案。谢谢。
    【解决方案3】:

    如果您可以在更改 DataContext 时将 ViewModel 属性设置为 true 或 false,则可以从 DataTrigger(EnterAction 和 ExitAction)触发 StoryBoard。因此 DataTrigger 将基于您的新 Bool 属性。

    【讨论】:

    • @Jobi - 最初我们做了类似的事情,re:使用 ViewModel 来处理触发器,但最终还是按照 Dabblernl 的建议使用了 DataContextChanged 事件,因为它将 UI 逻辑保留在UI 和模型之外。
    猜你喜欢
    • 2013-04-04
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 2017-06-24
    • 2011-01-23
    • 2012-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多