通过重新排序项目的WPF ListView动画?

时间:2009-07-30 15:32:51

标签: wpf listview animation controls

我想做几年前在WPF演示中看到的事情。我不知道它是如何完成的,但我知道可以这样做,这就是我的问题。

在演示中,有一个带有ListView或ListBox的WPF应用程序,其中包含很多项目。每个ListView都重新排序了列表中已更改位置的项目。但是ListView不仅仅是刷新了,实际上有一个项目的动画移动到新的位置。

这个应用程序非常酷,现在这正是我需要的。我们计划进行实时数据排名应用程序,这种动画将是完美的。

但我的团队中没有人知道如何做到这一点。我正在考虑一个ObservableCollection和Databinding,但其余的对我来说完全是个谜。

任何提示或想法都会有很大帮助。我相信有人已经这样做了。当WPF是新手时,我亲眼看到了它,但我不知道从哪里开始寻找。

3 个答案:

答案 0 :(得分:4)

还可以使用自定义面板。查理对于覆盖布局几乎是正确的。要创建自定义面板,您必须覆盖从MeasureOverride继承的ArrangeOverrideSystem.Windows.Controls.Panel方法。

CodeProject上的

This project演示了几个自定义面板,您可以在其中研究它们的动画效果。当FanPanel从一行的末尾移动到另一行的开头或反之时,ArrangeOverride动画重新定位项目。

This tutorial还演示了ValueConverter中的开始动画。

我还没有尝试过,但您也可以使用排名值和自定义Canvas将排名转换为某个位置,以便在{{1}内推广此类动画}。但是,自定义面板可以更好地自包含,允许您更改排名数据中使用的DataTemplate,让每个人都告诉Panel他们想要多高(假设他们是垂直排列。)

答案 1 :(得分:1)

我从未尝试过这样的事情,但我怀疑至少,你需要为ListView编写自己的ViewBase。有herehere的优秀示例。然后真正的问题是,你用什么事件动画触发?试着看看ItemsControl.ItemsChanged。

最终,您可能必须继承ItemsControl并覆盖多个布局并安排方法才能获得此功能。即使使用WPF的超可自定义控件,这也不是一项容易的任务,并且需要比XAML更多的代码隐藏。

答案 2 :(得分:1)

另一种选择是使用Microsoft的ReorderThemeTransition。在网站上的示例中:

<!--XAML-->
<StackPanel>
<Button x:Name="AddItemButton" Content="AddItem" Click="AddItemButton_Click"/>
<ItemsControl x:Name="ItemsList">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapGrid>
                <WrapGrid.ChildrenTransitions>
<!-- Apply a ReorderThemeTransition that will run when child elements are reordered. -->
                    <TransitionCollection>
                        <ReorderThemeTransition/>
                    </TransitionCollection>
                </WrapGrid.ChildrenTransitions>
            </WrapGrid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <!-- Initial items. -->
    <Rectangle Width="100" Height="100" Fill="Red"/>
    <Rectangle Width="100" Height="100" Fill="Green"/>
    <Rectangle Width="100" Height="100" Fill="Blue"/>            
</ItemsControl>            
</StackPanel>

然后在代码中:

//    C#
private void AddItemButton_Click(object sender, RoutedEventArgs e)
{
    Rectangle newItem = new Rectangle();
    Random rand = new Random();

    newItem.Height = 100;
    newItem.Width = 100;
    newItem.Fill = new SolidColorBrush(Color.FromArgb(255,
            (byte)rand.Next(0, 255), (byte)rand.Next(0, 255), (byte)rand.Next(0, 255)));

    // Insert a new Rectangle of a random color into the ItemsControl at index 2.
    ItemsList.Items.Insert(2, newItem);
}