发生事件时在 DataTemplate 中运行 Storyboard [英] Run Storyboard inside DataTemplate when an event occurs

查看:31
本文介绍了发生事件时在 DataTemplate 中运行 Storyboard的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 ToggleButton 和一个 ItemsControl.ItemsControl 的项有一个 DataTemplate.当 ToggleButton 的检查状态更改时,如何为 ItemsControl 的每个项目设置动画?

I have a ToggleButton and an ItemsControl. The ItemsControl's items have a DataTemplate. How can I animate each of ItemsControl's items, when ToggleButton's check state is changed?

在下面的代码中,您可以看到当用户单击 ToggleButton 时,V 形会旋转.我希望 ItemsControl 中的项目也有动画效果.我添加了一个带有ItemAnimation"键的故事板.我认为应该以某种方式在用户点击按钮时触发它.

In the following code, you can see when the user clicks on the ToggleButton, the chevron rotates. I want the items in the ItemsControl to animate as well. I added a Storyboard with the key "ItemAnimation". I think somehow it should be triggered when the user clicks on the button.

<Window x:Class="WinClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WinClient"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.Resources>
        <DataTemplate x:Key="ShortcutButton">
            <DataTemplate.Resources>
                <Storyboard x:Key="ItemAnimation" AutoReverse="False">
                    <DoubleAnimation Storyboard.TargetName="Trans" Storyboard.TargetProperty="Y" Duration="0:0:0.25" From="-100" To="0" EasingFunction="{StaticResource AnimationEase}" />
                </Storyboard>
            </DataTemplate.Resources>
            <Border Width="100" Height="100" Background="White" CornerRadius="50" x:Name="ContainerBorder">
                <Border.RenderTransform>
                    <TranslateTransform x:Name="Trans"/>
                </Border.RenderTransform>
                <TextBlock Text="{Binding Name}" FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <StackPanel VerticalAlignment="Top" Margin="50">
        <Border Width="150" Height="150" CornerRadius="75" Background="White" BorderBrush="#FFC12121">
            <Grid>
                <Image Source="Resources/logo.png" />
                <ToggleButton Width="40" Height="40" VerticalAlignment="Bottom" IsChecked="True" Command="{Binding ClickCommand}">
                    <Image x:Name="chevron" Source="Resources/chevron-down.png" Width="32" Height="32">
                        <Image.RenderTransform>
                            <RotateTransform CenterX="16" CenterY="16"/>
                        </Image.RenderTransform>
                    </Image>
                    <ToggleButton.Triggers>
                        <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="0" To="180" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="ToggleButton.Checked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="180" To="0" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ToggleButton.Triggers>
                </ToggleButton>
            </Grid>
        </Border>
        <ItemsControl ItemsSource="{Binding Shortcuts}"
                      RenderTransform="{Binding Transform}"
                      ItemTemplate="{StaticResource ShortcutButton}"/>
    </StackPanel>
</Window>

更新

我希望图标从徽标后面移动到它们的位置.这意味着第一个将移动 100 个像素,第二个 200,第三个 300,依此类推.这是我想要的图片:

Update

I want the icons to move from behind the logo to their positions. Meaning the first one would move 100 pixels, the second 200, the third 300, and so on. Here's what I want in a picture:

推荐答案

您提供的代码不完整:没有 AnimationEase 资源,没有 DataContext (ViewModel) 代码.因此,实现示例并不准确.
该示例使用回退属性 Tag.
一个初始值被写入其中,然后它被动画化.
ItemsControl 项的转换绑定到此属性.
因此,它们也都是同步动画的.

You gave incomplete code: no AnimationEase resource, no DataContext (ViewModel) code. Therefore, the implementation example is not accurate.
The example uses the fallback property Tag.
An initial value is written into it and then it is animated.
The transformation of ItemsControl items is bound to this property.
Therefore, they, too, are all synchronously animated.

<Window x:Class="WinClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WinClient" xmlns:specialized="clr-namespace:System.Collections.Specialized;assembly=System" xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="650" Width="800">
    <Window.Resources>
        <specialized:StringCollection x:Key="source">
            <sys:String>First</sys:String>
            <sys:String>Second</sys:String>
        </specialized:StringCollection>
        <DataTemplate x:Key="ShortcutButton">
            <Border Width="100" Height="100" Background="White" CornerRadius="50" x:Name="ContainerBorder">
                <Border.RenderTransform>
                    <TranslateTransform Y="{Binding Tag, ElementName=itemsControl}" />
                </Border.RenderTransform>
                <TextBlock Text="{Binding}" FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </DataTemplate>
    </Window.Resources>
    <StackPanel VerticalAlignment="Top" Margin="50">
        <Border Width="150" Height="150" CornerRadius="75" Background="White" BorderBrush="#FFC12121">
            <Grid>
                <Image Source="Resources/logo.png"/>
                <ToggleButton Width="40" Height="40" VerticalAlignment="Bottom" IsChecked="True" >
                    <Image x:Name="chevron" Source="Resources/chevron-down.png" Width="32" Height="32">
                        <Image.RenderTransform>
                            <RotateTransform CenterX="16" CenterY="16"/>
                        </Image.RenderTransform>
                    </Image>
                    <ToggleButton.Triggers>
                        <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="0" To="180" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                    <DoubleAnimation Storyboard.TargetName="itemsControl" Storyboard.TargetProperty="Tag" Duration="0:0:0.25" From="-100" To="0" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="ToggleButton.Checked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="180" To="0" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ToggleButton.Triggers>
                </ToggleButton>
            </Grid>
        </Border>
        <ItemsControl x:Name="itemsControl"
                      ItemsSource="{DynamicResource source}"
                      ItemTemplate="{StaticResource ShortcutButton}">
            <ItemsControl.Tag>
                <sys:Double>10</sys:Double>
            </ItemsControl.Tag>
        </ItemsControl>
    </StackPanel>
</Window>

添加与以下说明有关:

问题是当我取消选中"时切换按钮,圆圈不会回到顶部.此外,我希望图标从徽标后面移动到它们的位置.这意味着第一个将移动 100 个像素,第二个 200,第三个 300,依此类推.

The problem is that when I "uncheck" the toggle button, the circles don't go back to the top. Also, I want the icons to move from behind the logo to their positions. Meaning the first one would move 100 pixels, the second 200, the third 300 and so on.

乘法的MultiConverter:

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace WinClient
{
    public class MultiplicationConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values == null || values.Length == 0)
                return DependencyProperty.UnsetValue;

            double product = 1;
            foreach (var value in values)
            {
                if (double.TryParse(value.ToString(), out double number))
                    product *= number;
                if (product == 0)
                    break;
            }
            return product;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        public static MultiplicationConverter Instance { get; } = new MultiplicationConverter();
    }

    public class MultiplicationConverterExtension : MarkupExtension
    {
        public override object ProvideValue(IServiceProvider serviceProvider)
            => MultiplicationConverter.Instance;
    }
}

XAML 示例:

<Window x:Class="WinClient.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WinClient"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        mc:Ignorable="d"
        Title="MainWindow" Height="650" Width="800">
    <Window.Resources>
        <sys:String x:Key="source">12345</sys:String>
        <DataTemplate x:Key="ShortcutButton">
            <Border Width="100" Height="100" Background="White" CornerRadius="50" x:Name="ContainerBorder">
                <TextBlock Text="{Binding}" FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </DataTemplate>
        <sys:Double x:Key="zero">0</sys:Double>
        <ItemsPanelTemplate x:Key="canvasTemplate">
            <Canvas/>
        </ItemsPanelTemplate>
        <Style x:Key="itemContainerStyle" TargetType="ContentPresenter">
            <Setter Property="Canvas.Top">
                <Setter.Value>
                    <MultiBinding Converter="{local:MultiplicationConverter}">
                        <Binding Path="(ItemsControl.AlternationIndex)" RelativeSource="{RelativeSource Self}"/>
                        <Binding Path="Tag" ElementName="itemsControl"/>
                    </MultiBinding>
                </Setter.Value>
            </Setter>
        </Style>
    </Window.Resources>
    <Grid VerticalAlignment="Top" Margin="50" HorizontalAlignment="Center">
        <Border x:Name="border" Width="150" Height="150" CornerRadius="75" Background="White" BorderBrush="#FFC12121"
                Panel.ZIndex="10">
            <Grid>
                <Image Source="Resources/logo.png"/>
                <ToggleButton Width="40" Height="40" VerticalAlignment="Bottom">
                    <Image x:Name="chevron" Source="Resources/chevron-down.png" Width="32" Height="32">
                        <Image.RenderTransform>
                            <RotateTransform CenterX="16" CenterY="16"/>
                        </Image.RenderTransform>
                    </Image>
                    <ToggleButton.Triggers>
                        <EventTrigger RoutedEvent="ToggleButton.Unchecked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="0" To="180" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                    <DoubleAnimation Storyboard.TargetName="itemsControl" Storyboard.TargetProperty="Tag" Duration="0:0:2" To="0" From="100" />
                                    <DoubleAnimation Storyboard.TargetName="itemsControlXY" Storyboard.TargetProperty="Y" Duration="0:0:2" To="0" From="{Binding ActualHeight, ElementName=border}" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                        <EventTrigger RoutedEvent="ToggleButton.Checked">
                            <BeginStoryboard>
                                <Storyboard>
                                    <DoubleAnimation Storyboard.TargetName="chevron" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)" From="180" To="0" Duration="0:0:0.3">
                                        <DoubleAnimation.EasingFunction>
                                            <PowerEase EasingMode="EaseIn" />
                                        </DoubleAnimation.EasingFunction>
                                    </DoubleAnimation>
                                    <DoubleAnimation Storyboard.TargetName="itemsControl" Storyboard.TargetProperty="Tag" Duration="0:0:2" From="0" To="100" />
                                    <DoubleAnimation Storyboard.TargetName="itemsControlXY" Storyboard.TargetProperty="Y" Duration="0:0:2" From="0" To="{Binding ActualHeight, ElementName=border}" />
                                </Storyboard>
                            </BeginStoryboard>
                        </EventTrigger>
                    </ToggleButton.Triggers>
                </ToggleButton>
            </Grid>
        </Border>
        <ItemsControl x:Name="itemsControl"
                      AlternationCount="{x:Static sys:Int32.MaxValue}"
                      ItemsSource="{DynamicResource source}"
                      ItemTemplate="{DynamicResource ShortcutButton}"
                      Tag="{StaticResource zero}"
                      ItemsPanel="{DynamicResource canvasTemplate}"
                      ItemContainerStyle="{DynamicResource itemContainerStyle}" RenderTransformOrigin="0.5,0.5">
            <ItemsControl.RenderTransform>
                <TranslateTransform x:Name="itemsControlXY" Y="0"/>
            </ItemsControl.RenderTransform>
        </ItemsControl>
    </Grid>
</Window>

Ответ дополнен в связи с дополнительным вопросом:

我尝试像这样使用标签:Opacity={Binding Path=Tag, ElementName=itemsControl, Converter={StaticResource tagToOpacityConverter}}"但问题是,我只得到标签的开始和结束值.这意味着我只得到 0 和 100 而不是两者之间的值.所以控件出现和消失

I tried using the Tag for it like this: Opacity="{Binding Path=Tag, ElementName=itemsControl, Converter={StaticResource tagToOpacityConverter}}" but the problem is, I only get the start and the end values of the Tag. Meaning I only get 0 and 100 not the values in between. So the control appears and disappears

实现示例(对之前代码的更改):

Implementation example (changes for the previous code):

    <Window.Resources>
        <sys:String x:Key="source">12345</sys:String>
        <sys:Double x:Key="percent">0.01</sys:Double>
        <DataTemplate x:Key="ShortcutButton">
            <Border Width="100" Height="100" Background="AliceBlue" CornerRadius="50" x:Name="ContainerBorder">
                <Border.Opacity>
                    <MultiBinding Converter="{local:MultiplicationConverter}">
                        <Binding Path="Tag" ElementName="itemsControl"/>
                        <Binding Source="{StaticResource percent}"/>
                    </MultiBinding>
                </Border.Opacity>
                <TextBlock Text="{Binding}" FontSize="60" HorizontalAlignment="Center" VerticalAlignment="Center"/>
            </Border>
        </DataTemplate>

这篇关于发生事件时在 DataTemplate 中运行 Storyboard的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆