假设:
<ScrollViewer VerticalScrollBarVisibility="Auto" >
<ItemsControl ItemsSource="{Binding Controls}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
其中“控件绑定”是包含某种用户控件的viewmodel中的ObservableCollection。
由于wrappanel中的内容居中,当前行为如下:
我想要的是在添加新的用户控件时添加“移动”转换/转换,即我想在添加每个UC时向左侧显示A / B ......的转换动画。
我更愿意在XAML中尽可能多地做,而不是打破MVVM模式。
奖金,我希望能够在移除UC时进行动画制作。
答案 0 :(得分:1)
我将Controls视为FrameworkElement的ObservableCollection 您可以使用以下代码:
<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
}