Анимированный ListView в WPF
Захотелось мне сделать добавление элемента в ListView анимированным: чтобы элемент выезжал из верхнего края списка.
Вот как я это делал:
1. Классы данных
class DataElement : INotifyPropertyChanged { private string caption; public string Caption { get { return this.caption; } set { this.caption = value; DoNotify("Caption"); } } public event PropertyChangedEventHandler PropertyChanged; private void DoNotify(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
Класс, экземпляры которого отображаются в списке. Реализует интерфейс INotifyPropertyChanged и имеет свойство Caption для отображения в списке.
class Data { public ObservableCollection<DataElement> Entities { get; private set; } public Data() { this.Entities = new ObservableCollection<DataElement>(); this.Entities.Add(new DataElement() { Caption = "First" }); this.Entities.Add(new DataElement() { Caption = "Second" }); this.Entities.Add(new DataElement() { Caption = "Third" }); this.Entities.Add(new DataElement() { Caption = "Fourth" }); } }
Класс, экземпляр которого будет являться контекстом данных окна. Содержит свойство — коллекцию отображаемых элементов и в конструкторе заполняет ее тестовыми данными.
2. Разметка
<Storyboard x:Key="NewElementAnimation"> <DoubleAnimation Duration="0:0:1" From="0" To="40" Storyboard.TargetProperty="Height" /> </Storyboard>
Добавляем в ресурсы окна эту анимацию, увеличивающую высоту элемента с 0 до 40 за 1 секунду.
<Style x:Key="AnimatingElement" TargetType="ScrollViewer"> <Style.Triggers> <EventTrigger RoutedEvent="Loaded"> <BeginStoryboard Storyboard="{StaticResource NewElementAnimation}" /> </EventTrigger> </Style.Triggers> </Style>
Так же добавляем в ресурсы стиль, который запускает эту анимацию для загруженных элементов. TargetType равен ScrollViewer потому, что элементы списка будут завернуты в ScrollViewer.
<StackPanel> <ListBox ItemsSource="{Binding Entities}"> <ListBox.ItemTemplate> <DataTemplate> <ScrollViewer Style="{StaticResource AnimatingElement}" VerticalScrollBarVisibility="Hidden" Loaded="ScrollViewer_Loaded"> <Label Content="{Binding Caption}" Height="40"/> </ScrollViewer> </DataTemplate> </ListBox.ItemTemplate> </ListBox> <Button Name="AddButton" Click="Button_Click">Add Item</Button> </StackPanel>
Разметка самой формы. ScrollViewer нужен для того, чтобы при нехватке высоты отображался низ содержимого, а не верх. Это достигается прокруткой вниз при загрузке ScrollViewer.
3. Код окна.
public MainWindow() { InitializeComponent(); this.DataContext = new Data(); }
Конструктор окна. Означивает контекст данных в новый экземпляр класса Data.
private void Button_Click(object sender, RoutedEventArgs e) { var data = (Data)this.DataContext; data.Entities.Insert(0, new DataElement() { Caption = "NewElement" }); }
Обработчик нажатия на кнопку. Добавляет новый элемент в список.
private void ScrollViewer_Loaded(object sender, RoutedEventArgs e) { (sender as ScrollViewer).ScrollToBottom(); }
Прокрутка ScrollViewer вниз при загрузке.