【问题标题】:WPF/MVVM - WrapPanel in ItemsControl, Animation on added childWPF/MVVM - ItemsControl 中的 WrapPanel,添加子项上的动画
【发布时间】:2016-02-18 19:42:12
【问题描述】:

给定:

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

其中“控件绑定”是包含某种用户控件的视图模型中的 ObservableCollection。

由于wrappanel中的内容居中,当前行为如下:

  • UC A 被添加到列表中,并显示在面板的中心。
  • UC B 被添加到列表中,UC A 向左移动,UC B 被添加到面板中。
  • UC C 被添加到列表中,UC A 和 B 向左移动,UC C 被添加到面板中。

我想要的是在添加新用户控件时添加“移动”翻译/过渡,即我想在添加每个 UC 时显示左侧 A/B..n 的过渡动画。

我希望尽可能多地使用 XAML,而不是破坏 MVVM 模式。

奖励,我也希望能够在删除 UC 时制作动画。

【问题讨论】:

    标签: wpf animation mvvm storyboard transition


    【解决方案1】:

    我将控件视为 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
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-18
      • 2011-01-17
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      相关资源
      最近更新 更多