Чтобы было ясно, у меня есть UserControl с DependencyProperty, к которому источник данных привязан извне, а ListBox.ItemSource связан с внутренне.
Означает ли это, что UserControl's DataContext
является источником данных, а ListBox внутри UserControl затем привязывается к источнику данных?Потому что это имело бы смысл.В противном случае, я не уверен, что вы имеете в виду - вы бы отредактировали вопрос и поделились частью своего кода / XAML, чтобы было немного более очевидно, с чем вы работаете?
Предполагая сценарий, который я обрисовал, длятеперь ObservableCollection
звучит как путь, и я действительно смог анимировать дополнения (и, вероятно, удаления) из ItemsControl только в XAML, без написания обработчиков событий.
Допустим, вы связываете ItemsSource
вашего ListBox с ObservableCollection<YourListItemDataObjects>
.Вы можете создать DataTemplate
, как показано ниже, и назначить его для свойства ItemTemplate
ListBox:
<DataTemplate>
<TextBlock Name="animatedTextBlock" Text="{Binding Name}">
<TextBlock.Background>
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>0.5,0.0</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>0.5,1.0</LinearGradientBrush.EndPoint>
<GradientStop Color="White" Offset="0.3"/>
<GradientStop x:Name="cellBackgroundBottomStopColor"
Color="Orange" Offset="0.9"/>
</LinearGradientBrush>
</TextBlock.Background>
<TextBlock.Triggers>
<EventTrigger SourceName="animatedTextBlock"
RoutedEvent="TextBlock.Loaded">
<BeginStoryboard Name="flashNewCell">
<Storyboard>
<ColorAnimation Storyboard.TargetName="cellBackgroundBottomStopColor"
Storyboard.TargetProperty="Color"
From="White" To="Orange"
Duration="0:0:1" AutoReverse="False"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger SourceName="animatedTextBlock"
RoutedEvent="TextBlock.MouseUp">
<RemoveStoryboard BeginStoryboardName="flashNewCell" />
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
</DataTemplate>
Вы увидите, что DataTemplate
вызовет визуализацию ListItems как TextBoxes, привязанных кName
свойство объектов в вашем ObservableCollection
(очевидно, измените это свойство на то, что подходит в вашем случае).
Сложный бит - это анимация.Обратите внимание на EventTrigger
, свойство RoutedEvent
которого равно "TextBlock.Loaded" .Это событие будет срабатывать всякий раз, когда элемент добавляется в ObservableCollection
, привязанный к ListBox, поскольку это вызывает создание нового ListBoxItem - и, таким образом, нового TextBlock, чье событие Loaded
сработает.
Аналогично, есть событие Unloaded, которое вы можете вызвать при удалении элемента.
Также обратите внимание, что свойство Storyboard.TargetName
ColorAnimation
относится к имени, которое мы дали второму GradientStop
составляет фон TextBlock.Это сообщает анимации, какой элемент в визуальном дереве TextBlock нужно изменить - типичные анимации WPF всегда применяются к свойствам зависимостей визуальных элементов.
Применение animation к EventTrigger позволяет применятьэффекты (цвета градиента, в данном случае, но вы можете поиграть с Opacity, чтобы также делать постепенное исчезновение и исчезновение) для элемента управления, когда его связанный источник данных изменяется.
Второй EventTrigger
впример активируется для события MouseUp
, которое происходит, когда пользователь щелкает этот TextBlock, и удаляет анимацию, которую мы применяли, когда TextBlock был загружен (обратите внимание на настройку AutoReverse="False"
для этой первой анимации, которая вызывает егосохранять конечное состояние до тех пор, пока мы не удалим его явно).
Теперь у нас есть ListBox, элементы которого «светятся» в течение нескольких секунд при добавлении, и который поддерживает выделенный цвет, пока мы не нажмем на них.
Очевидно, что это только отправная точка - шаблоны данных и анимацияОбе глубокие темы вы можете исследовать дальше.Но я надеюсь, что вы найдете это полезным примером мощных возможностей связывания WPF и их потенциала, позволяющего вам определять свой пользовательский интерфейс только с помощью XAML.