2015-11-17 3 views
1

Дано:WPF/MVVM - WrapPanel в ItemsControl, анимация на добавленную ребенка

<ScrollViewer VerticalScrollBarVisibility="Auto" > 
    <ItemsControl ItemsSource="{Binding Controls}"> 
     <ItemsControl.ItemsPanel> 
      <ItemsPanelTemplate> 
       <WrapPanel />    
      </ItemsPanelTemplate> 
     </ItemsControl.ItemsPanel> 
    </ItemsControl> 
</ScrollViewer> 

Где "Управление связывания" является ObservableCollection в ViewModel, содержащей какой-то UserControls.

По мере того как содержание в WrapPanel центрирован, текущее поведение выглядит следующим образом:

  • UC А добавляется в список, и отображается в центре панели.
  • UC B добавлен в список, UC A перемещается влево, а UC B добавляется к панели.
  • UC C добавлен в список, UC A и B перемещается влево, а на панель добавляется UC C.

То, что я хочу, чтобы добавить «движение» перевод/переход, когда добавляется новый UserControl, то есть я хочу показать анимировать переход A/B..n влево, как каждый UC добавляется.

Я бы предпочел сделать как можно больше в XAML, а не нарушать шаблон MVVM.

enter image description here

Bonus, я хочу, чтобы иметь возможность одушевленные, когда UC удаляется тоже.

ответ

1

Я считаю управления как ObservableCollection из FrameworkElement Вы можете использовать этот код:

<Window x:Class="Marathonbet.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Loaded="MainWindow_OnLoaded" Title="MainWindow" Height="350" Width="525" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}"> 
    <Window.Resources> 
     <Storyboard x:Key="OnLoaded1"> 
      <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Margin)" > 
       <EasingThicknessKeyFrame KeyTime="0" Value="20,0,0,0"/> 
       <EasingThicknessKeyFrame KeyTime="0:0:0.4" Value="5"/> 
      </ThicknessAnimationUsingKeyFrames> 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)" > 
       <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="55"/> 
      </DoubleAnimationUsingKeyFrames> 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" > 
       <EasingDoubleKeyFrame KeyTime="0" Value="0"/> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.8" Value="1"/> 
      </DoubleAnimationUsingKeyFrames> 
     </Storyboard> 
     <Storyboard x:Key="OnUnloaded1" > 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)"> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/> 
      </DoubleAnimationUsingKeyFrames> 
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Width)"> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="55"/> 
       <EasingDoubleKeyFrame KeyTime="0:0:0.4" Value="0"/> 
      </DoubleAnimationUsingKeyFrames> 
     </Storyboard> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="*"/> 
      <RowDefinition Height="Auto"/> 
     </Grid.RowDefinitions> 
     <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="0"> 
      <ItemsControl ItemsSource="{Binding Controls}" x:Name="x"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <WrapPanel HorizontalAlignment="Center"/> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
      </ItemsControl> 
     </ScrollViewer> 
     <Button Grid.Row="1" Content="Add" Margin="5" HorizontalAlignment="Left" Padding="15,2,15,2" Click="btAdd_OnClick"/> 
     <Button Grid.Row="1" Content="Remove" Margin="64,5,0,5" HorizontalAlignment="Left" Padding="15,2,15,2" Click="btRemove_OnClick"/> 
    </Grid> 
</Window> 

код позади

public class MyObservableCollection : ObservableCollection<FrameworkElement> 
    { 

     private Storyboard unloadedStoryboard; 

     public Storyboard UnloadedSotryBoard 
     { 
      get { return unloadedStoryboard; } 
      set 
      { 
       unloadedStoryboard = value; 
       unloadedStoryboard.Completed += UnloadedStoryboardOnCompleted; 
      } 
     } 

     public Storyboard LoadedSotryBoard { get; set; } 

     protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e) 
     { 
      if (e.Action == NotifyCollectionChangedAction.Add) 
      { 
       foreach (FrameworkElement item in e.NewItems) 
        item.BeginStoryboard(LoadedSotryBoard); 
      } 
      base.OnCollectionChanged(e); 
     } 

     private HashSet<int> indexesToRemove = new HashSet<int>(); 

     protected override void RemoveItem(int index) 
     { 
      indexesToRemove.Add(index); 
      var item = Items[index]; 
      UnloadedSotryBoard.Begin(item); 
     } 

     private void UnloadedStoryboardOnCompleted(object sender, EventArgs eventArgs) 
     { 
      foreach (var i in new HashSet<int>(indexesToRemove)) 
      { 
       base.RemoveItem(i); 
       indexesToRemove.Remove(i); 
      } 
     } 

    } 

    public partial class MainWindow 
    { 

     public MyObservableCollection Controls { get; set; } 


     #region Constructors 

     public MainWindow() 
     { 
      Controls = new MyObservableCollection(); 
      InitializeComponent(); 
      Controls.LoadedSotryBoard = (Storyboard) FindResource("OnLoaded1"); 
      Controls.UnloadedSotryBoard = (Storyboard) FindResource("OnUnloaded1"); 
     } 

     #endregion 


     #region Events 

     private void MainWindow_OnLoaded(object sender, RoutedEventArgs e) 
     { 
      Controls.Add(new MyControl {DataContext = "A"}); 
      Controls.Add(new MyControl {DataContext = "B"}); 
      Controls.Add(new MyControl {DataContext = "C"}); 
     } 

     private void btAdd_OnClick(object sender, RoutedEventArgs e) 
     { 
      Controls.Add(new MyControl {DataContext = (char) new Random().Next(0, Byte.MaxValue)}); 
     } 

     private void btRemove_OnClick(object sender, RoutedEventArgs e) 
     { 
      if (Controls.Count == 0) 
       return; 
      Controls.RemoveAt(Controls.Count - 1); 
     } 

     #endregion 
    } 
Смежные вопросы