c# - 我如何一次为一个堆栈面板项目制作动画?

标签 c# wpf silverlight xaml animation

假设我有一个包含一些项目的 StackPanel。当我加载我的 View 时,我想对它们应用一些动画。但我希望每个项目都按顺序进行动画处理,一个接一个。我该怎么做呢?特别是,是否有一种干净的方法可以在 MVVM 框架中执行此操作?

编辑 - 我应该提一下,项目通过 ItemsControl 数据绑定(bind)到 StackPanel,这可能会使事情变得更加困难。看起来像这样

                   <ItemsControl x:Name="Items">
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel />
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Button Content="{Binding ButtonName}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>

为清楚起见,省略了一些 UI 代码。

最佳答案

复制/粘贴/编译/运行:我会给出一个解释,但主题太多无法涵盖。基本上,该示例展示了如何在不卡住 UI 的情况下在后台进行 MultiTrigger、动画、加载项目,以及如何使用 PropertyChanged 来通知 UI。 享受吧。

这是 XAML

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="MainWindow" Height="350" Width="525"
    x:Name="wnd">
<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BoolToVisibility" />
</Window.Resources>

<ItemsControl x:Name="Items" ItemsSource="{Binding TestItems, ElementName=wnd}" Loaded="Items_Loaded">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Button x:Name="item" Content="{Binding DisplayString}" Margin="5">
                <Button.Style>
                    <Style TargetType="{x:Type Button}">
                        <Setter Property="Opacity" Value="0"/>
                        <Setter Property="Visibility" Value="{Binding Path=IsVisible, Converter={StaticResource BoolToVisibility}}"/>
                        <Style.Triggers>
                            <MultiDataTrigger>
                                <MultiDataTrigger.Conditions>
                                    <Condition Binding="{Binding IsLoading}" Value="True"/>
                                    <Condition Binding="{Binding IsVisible}" Value="True"/>
                                </MultiDataTrigger.Conditions>
                                <MultiDataTrigger.EnterActions>
                                    <BeginStoryboard>
                                        <Storyboard >
                                            <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:1.5" AccelerationRatio="0.3"/>
                                        </Storyboard>
                                    </BeginStoryboard>
                                </MultiDataTrigger.EnterActions>
                            </MultiDataTrigger>
                        </Style.Triggers>
                    </Style>
                </Button.Style>
            </Button>                   
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

下面是它背后的代码:

using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApplication1
{

public partial class MainWindow : Window
{
    private List<TestItem> _items;
    public List<TestItem> TestItems
    {
        get
        {
            if(_items == null)
            {
                _items = new List<TestItem>();
                for(int i = 0; i < 10; i++)
                    _items.Add(new TestItem{ DisplayString = i.ToString(CultureInfo.InvariantCulture), IsVisible = true});
            }
                return _items;
        }
    }

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Items_Loaded(object sender, RoutedEventArgs e)
    {
        /*in background so not to freeze the UI thread*/
        Task.Factory
            .StartNew(() =>
                        {
                            foreach (var item in TestItems)
                            {
                                item.IsLoading = true;
                                item.IsVisible = true;
                                /*using sleep as quick and dirty just to slow down loading and show the animation (otherwise it's a no-no )*/
                                Thread.Sleep(500);
                            }
                        }
            );
    }
}

public class TestItem : INotifyPropertyChanged
{
    private string _displayString;
    private bool _isVisible;
    private bool _isLoading;

    public string DisplayString
    {
        get { return _displayString; } 
        set
        {
            if (_displayString == value) return;
            _displayString = value;
            RaisePropertyChanged("DisplayString");
        }
    }

    public bool IsVisible
    {
        get { return _isVisible; }
        set
        {
            if (_isVisible == value) return;
            _isVisible = value;
            RaisePropertyChanged("IsVisible");
        }
    }

    public bool IsLoading
    {
        get { return _isLoading; }
        set
        {
            if (_isLoading == value) return;
            _isLoading = value;
            RaisePropertyChanged("IsLoading");
        }
    }


    public event PropertyChangedEventHandler PropertyChanged;

    private void RaisePropertyChanged(string propertyName)
    {
        if(PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
}

关于c# - 我如何一次为一个堆栈面板项目制作动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4341431/

相关文章:

c# - 如何从 WPF 应用程序中将 Windows 资源管理器打开到特定目录?

wpf - 如何使用 Prism 6 正确制作 CanExecute 触发器

wpf - ViewModel 如何在 WPF/MVVM 中的 View 中请求更新?

Silverlight DependencyProperty.SetCurrentValue 等效项

c# - 同步 IIS Web 服务器配置

c# - Dictionary ContainsKey 似乎不适用于 string[] 键

c# - Task.Run 在同一线程上继续导致死锁

wpf - WPF WindowsFormsHost大小调整

silverlight - 标准 .Net 2 dll 是否与 silverlight 2.0 运行时兼容?

windows - 我们如何禁用 silverlight windows phone 7 中文本框的默认键盘?