2010-12-03 7 views
2

몇 가지 항목이있는 StackPanel이 있다고 가정 해 보겠습니다. 내보기를로드 할 때 일부 애니메이션을 적용하고 싶습니다. 그러나 각 항목을 순서대로 하나씩 애니메이트하기를 원합니다. 이 일을 어떻게 하죠? 특히 MVVM 프레임 워크에서이를 수행 할 수있는 명확한 방법이 있습니까?한 번에 하나의 스택 패널 항목에 애니메이션을 적용하려면 어떻게해야합니까?

편집 - 항목이 ItemsControl을 통해 StackPanel에 데이터 바인딩된다는 사실을 언급해야합니다. 이로 인해 작업이 상당히 어려워 질 수 있습니다. 모양은 다음과 같습니다.

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

일부 UI 코드는 생략했습니다.

답변

1

복사/붙여 넣기/컴파일/실행 : 설명을하지만 너무 많은 주제를 다루고 싶습니다. 기본적으로이 샘플에서는 UI를 고정하지 않고 백그라운드에서 MultiTrigger, Animate, Load Items를 사용하는 방법과 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)); 
    } 
} 
} 
관련 문제