无法让(相当简单)WPF 动画工作
我正在尝试在 WPF 中获取动画消息面板,但到目前为止尚未取得成功。
情况是这样的:
- 我有一个带有
StackPanel
的用户控件,其中包含绑定到控件的视图模型对象 (ViewModel.Messages) 中的(可观察)集合的
ItemsControl
)。 - 当我需要向用户展示消息时,我会将这些消息(作为
MessageVM
实例)添加到可观察集合中。
ItemsControl
的可见性绑定到名为 ViewModel.CountVisibleMessages
的整数属性,并且有一个转换器负责将 0 转换为 Visibility.Hidden
以及Visibility.Visible
的正值。
这很好用。当消息添加到集合中时,StackPanel
自动变得可见,并且当用户(或计时器)删除最后一条消息时,它会隐藏。当然,StackPanel 的高度会自动调整以适应所有消息。
为了让一切看起来更好,我更希望 StackPanel 使用运行 300 毫秒的动画来调整自身大小。 (最终我也希望它能够加速和减速,但这超出了我现在的野心。
我已经实验了几个小时,但我觉得我还没有接近。 下面是我目前的(甚至还没有接近工作)XAML:(
<StackPanel Orientation="Vertical"
VerticalAlignment="Top"
Visibility="{Binding CountVisibleMessages, Converter={StaticResource IntToVisibility}}"
Height="Auto"
Background="{DynamicResource HmiBackColorLightBrush}">
<StackPanel.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding CountVisibleMessagesChanged}" Value="True" ><!-- I suppose I shopuld've used a Routed Event here but I just needed to get it triggered -->
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Margin.Bottom"
From="100" <!-- Just a made up value to test the concept -->
To="0"
Duration="0:0:0:3"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<ItemsControl ItemsSource="{Binding Messages}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{DynamicResource Message}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Text}" Margin="3" Style="{Binding MessageType, Converter={StaticResource MessageTypeToStyle}, ConverterParameter={x:Type TextBlock}}" /> <!-- using dynamic styling here -->
<RadioButton Grid.Column="1" Style="{DynamicResource HmiCloseMessageButton}" IsChecked="{Binding IsVisible, Converter={StaticResource BoolToVisibility}, ConverterParameter=true}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
我确实意识到上面的 XAML 不会让 StackPanel 缓慢地自动调整大小。这只是一个让任何事情发生的实验)。
我认为这不会太困难(这是许多程序中相当标准的 UI 行为),因此如果有人能够为我指出正确的方向,我将不胜感激。
干杯
I'm trying to get a message panel animated in WPF but has so far achieved no success.
This is the situation:
- I have a user control with a
StackPanel
containing anItemsControl
bound to an (observable) collection in the control's View Model object (ViewModel.Messages
). - When I need to present the user with messages I ad those (as
MessageVM
instances) to the observable collection.
The ItemsControl
's visibility is bound to an integer property called ViewModel.CountVisibleMessages
and there's a converter taking care of translating 0 to Visibility.Hidden
and positive values to Visibility.Visible
.
This works just fine. When a message gets added to the collection the StackPanel
automatically becomes visible and as the user (or a timer) removes the last message it gets hidden. The StackPanel
height is automatically adjusted to fit all messages of course.
To make everything look nicer I would prefer it if the StackPanel
resized itself using an animation running for, say, 300 ms. (Ultimately I would also like it to accelerate and deccelerate but that's beyond my ambition right now.
I have experimented for a few hours now but I feel I'm not even close.
Below is my current (not even close to working) XAML at the moment:
<StackPanel Orientation="Vertical"
VerticalAlignment="Top"
Visibility="{Binding CountVisibleMessages, Converter={StaticResource IntToVisibility}}"
Height="Auto"
Background="{DynamicResource HmiBackColorLightBrush}">
<StackPanel.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding CountVisibleMessagesChanged}" Value="True" ><!-- I suppose I shopuld've used a Routed Event here but I just needed to get it triggered -->
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Margin.Bottom"
From="100" <!-- Just a made up value to test the concept -->
To="0"
Duration="0:0:0:3"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<ItemsControl ItemsSource="{Binding Messages}" >
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Style="{DynamicResource Message}">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="15" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Text}" Margin="3" Style="{Binding MessageType, Converter={StaticResource MessageTypeToStyle}, ConverterParameter={x:Type TextBlock}}" /> <!-- using dynamic styling here -->
<RadioButton Grid.Column="1" Style="{DynamicResource HmiCloseMessageButton}" IsChecked="{Binding IsVisible, Converter={StaticResource BoolToVisibility}, ConverterParameter=true}" />
</Grid>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
(I do realize the above XAML won't get the StackPanel to auto-resize slowly. It's just an experiment to get anything happening).
This can't be too difficult I suppose (it's a pretty standard UI behavior in many programs) so I'd appreciate it if anyone could point me in the right directions.
Cheers
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您确定要调整下边距吗?堆栈面板 VerticalAlignment 位于顶部。如果您想更改高度,请将 StoryBoard 属性绑定到高度。您知道您的 StoryBoard 是否正在启动吗?
Are you sure you want to adjust the bottom margin? The stack panel VerticalAlignment is top. If you want to change the Height then bind your StoryBoard Property to Height. Do you know if your StoryBoard is firing?
关键点是
ExitActions
对于基于EnterAction
的 dataTrigger 动画是必需的。所以以下内容似乎适用于我的情况......让我知道这是否有帮助。
The key point is
ExitActions
are necessary forEnterAction
based dataTrigger animations. So the following seems to be working in my case ....Let me know if this helps.