ListView CustomRoutedEvent在行上触发动画

时间:2011-06-04 09:23:16

标签: wpf listview animation triggers

嗨大家我有一个列表视图绑定到observableCollection,当一个新项目进来时,它会闪烁该行。

到目前为止,我的itemcontainer样式中有一个事件触发器。

<Style TargetType="WpfApplication2:CustomListViewItem">
    <Style.Triggers>
        <EventTrigger RoutedEvent="<My Custom Routed Event>">
            <BeginStoryboard>
                <Storyboard >
                    <ColorAnimation Storyboard.TargetProperty="(Background).(SolidColorBrush.Color)"
                                    From="Navy" 
                                    To="White"
                                    Duration="0:0:0.4"
                                    AutoReverse="True"/>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Style.Triggers>                   
</Style>

还有一个自定义路由事件,我想在添加新项目时触发。 发现很难理解我应该把这个路由事件放在哪里以及如何解雇它。

由于

1 个答案:

答案 0 :(得分:0)

我不认为这属于ItemContainerStyle,因为项目管理位于ListView本身的更高级别。

您可以采用Blend SDK中的行为来解决此问题,例如:

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<ListView ItemsSource="{Binding DpData}">
    <i:Interaction.Behaviors>
        <b:FlashNewRowBehavior />
    </i:Interaction.Behaviors>
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Name}" />
            <GridViewColumn DisplayMemberBinding="{Binding Occupation}" />
        </GridView>
    </ListView.View>
</ListView>
class FlashNewRowBehavior : Behavior<ListView>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        AssociatedObject.Loaded += new System.Windows.RoutedEventHandler(AssociatedObject_Loaded);
    }

    void AssociatedObject_Loaded(object sender, System.Windows.RoutedEventArgs e)
    {
        var itemsSource = AssociatedObject.ItemsSource;
        if (itemsSource is INotifyCollectionChanged)
        {
            var collection = itemsSource as INotifyCollectionChanged;
            collection.CollectionChanged += (s, cce) =>
                {
                    if (cce.Action == NotifyCollectionChangedAction.Add)
                    {
                        // This code sadly is rather unclean, some wait is necessary or the ItemContainerGenerator will return null
                        Wait(TimeSpan.FromSeconds(0.01));

                        var itemContainer = AssociatedObject.ItemContainerGenerator.ContainerFromItem(cce.NewItems[0]) as ListViewItem;
                        if (itemContainer != null)
                        {
                            Storyboard sb = new Storyboard();
                            ColorAnimation anim = new ColorAnimation()
                            {
                                // From is not really needed (if you want to animate from the current background color at least)
                                From = Colors.Navy,

                                // I would create properties instead of hardcoded values
                                To = Colors.White,
                                Duration = (Duration)TimeSpan.FromSeconds(0.4),

                                AutoReverse = true
                            };
                            Storyboard.SetTargetProperty(anim, new PropertyPath("Background.Color"));
                            Storyboard.SetTarget(anim, itemContainer);
                            sb.Children.Add(anim);
                            sb.Begin(); 
                        }
                    }
                };
        }
    }

    private static void Wait(TimeSpan timeout)
    {
        var frame = new DispatcherFrame();
        new Thread((ThreadStart)(() =>
        {
            Thread.Sleep(timeout);
            frame.Continue = false;
        })).Start();
        Dispatcher.PushFrame(frame);
    }
}