如何仅在DependencyProperty上触发动画更改(不是默认值)?

时间:2016-05-17 11:23:16

标签: c# wpf user-controls

似乎我总是被最简单的东西所困扰...我有一个带有自定义bool DependencyProperty'GpoModule'的UserControl。

默认设置为false。

我在'GpoModule'= true时触发了FadeIn动画,在'GpoModule'= false时触发了FadeOut动画。

我的问题是,当加载控件时,会触发FadeOut动画,我希望仅在属性更改时触发动画(或者至少在加载时不是默认值)。我怀疑我可能要定义某种事件触发器,但我希望避免这种情况。

的DependencyProperty:

    public bool GpoModule {
        get { return (bool)GetValue(GpoModuleProperty); }
        set { SetValue(GpoModuleProperty, value); }
    }
    public static readonly DependencyProperty GpoModuleProperty =
        DependencyProperty.Register("GpoModule", typeof(bool),
            typeof(ModuleIndicator), new UIPropertyMetadata(false));

动画:

 <UserControl.Resources>
    <Duration x:Key="D">0:0:0.6</Duration>
    <Storyboard x:Key="SbFadeOut">
        <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)"
                         From="38" To="0"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
        <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Height)"
                         From="38"
                         To="0"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)"
                         From="1"
                         To="0"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
    </Storyboard>
    <Storyboard x:Key="SbFadeIn">
        <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Width)"
                         From="0" To="38"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
        <DoubleAnimation Storyboard.TargetProperty="(FrameworkElement.Height)"
                         From="0"
                         To="38"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
        <DoubleAnimation Storyboard.TargetProperty="(UIElement.Opacity)"
                         From="0"
                         To="1"
                         Duration="{StaticResource D}">
            <DoubleAnimation.EasingFunction>
                <QuadraticEase EasingMode="EaseInOut" />
            </DoubleAnimation.EasingFunction>
        </DoubleAnimation>
    </Storyboard>        
</UserControl.Resources>

动画元素:

   <Viewbox x:Name="GpoIndicator"
            VerticalAlignment="Center" HorizontalAlignment="Center"
                              Stretch="Fill" Width="0" Height="0">
        <Grid Height="38" Width="38">
            <Ellipse Height="38"
                    Fill="{DynamicResource App.Primary.Light}"
                    Stroke="{DynamicResource App.Border}" />
            <TextBlock Width="38"
                    Height="38"
                    Margin="0"
                    HorizontalAlignment="Left"
                    VerticalAlignment="Top"
                    FontFamily="{DynamicResource AppFont}"
                    FontSize="30"
                    FontWeight="Bold"
                    Foreground="{DynamicResource ResourceKey=App.Accent.Secondary}"
                    Padding="0,2,0,0"
                    Text="G"
                    TextAlignment="Center"
                    TextWrapping="Wrap"/>
        </Grid>
        <Viewbox.Style>
            <Style TargetType="Viewbox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}"
                             Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Name="GpoIn">
                                <Storyboard>
                                    <StaticResource ResourceKey="SbFadeIn" />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="GpoIn" />
                        </DataTrigger.ExitActions>                            
                    </DataTrigger>
                    <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}"
                                 Value="False">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Name="GpoOut">
                                <Storyboard>
                                    <StaticResource ResourceKey="SbFadeOut" />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="GpoOut" />
                        </DataTrigger.ExitActions>
                    </DataTrigger>                       
                </Style.Triggers>
            </Style>
        </Viewbox.Style>
    </Viewbox>

谢谢!

编辑:我应该提到还有另外两个'指标'对象/孩子 - 'RedesignIndicator'和'NovellIndicator'。每个都有各自的bool DependencyProperties。
在提出问题之前我尝试使用多个条件。我的第一次尝试是将条件设置为'IsLoaded',但没有效果。
我的第二次尝试是使用另一个Dependency属性'AnimationLocked',默认设置为true,并尝试了两个变体。
一:在属性改变回调时将AnimationLocked设置为false(这具有在其他一个子对象上触发FadeOut动画的副作用和
二:在UserControl.Loaded事件上设置AnimationLocked为false(没有效果)

2 个答案:

答案 0 :(得分:0)

您可以使用多数据触发器:

<Viewbox.Style>
    <Style TargetType="Viewbox">
        <Style.Triggers>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsLoaded}" Value="True" />
                    <Condition Binding="{Binding GpoModule}" Value="True" />
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterAction>
                    ... fade in animation
                </MultiDataTrigger.EnterAction>
            </MultiDataTrigger>
            <MultiDataTrigger>
                <MultiDataTrigger.Conditions>
                    <Condition Binding="{Binding IsLoaded}" Value="True" />
                    <Condition Binding="{Binding GpoModule}" Value="False" />
                </MultiDataTrigger.Conditions>
                <MultiDataTrigger.EnterAction>
                    ... fade out animation
                </MultiDataTrigger.EnterAction>
            </MultiDataTrigger>
        </Style.Triggers>
    </Style>
</Viewbox.Style>

IsLoaded是另一个依赖项属性,在控件true事件处理程序中设置为Loaded

这种方式动画只会在IsLoaded == true时发生。

P.S。:不确定是否必须在控制IsLoaded = false事件处理程序中设置Unloaded

答案 1 :(得分:0)

我最终解决的解决方案是在我的控件上为三个孩子的“模块指示器”中的每一个添加一个“AnimationLocked”bool DependencyProperty。 'AnimationLocked'的默认值为true,在'Module'bool DependencyProperty回调中设置为false,这样可以确保动画被阻止,直到第一次用户交互手动更改属性为止。我希望有一些内置的方法可以防止触发器“触发”默认值。这似乎非常不优雅,我仍然愿意接受其他建议。

UserControl代码隐藏:

 public bool GpoAnimationLocked
    {
        get { return (bool)GetValue(GpoAnimationLockedProperty); }
        set { SetValue(GpoAnimationLockedProperty, value); }
    }
    public static readonly DependencyProperty GpoAnimationLockedProperty =
        DependencyProperty.Register("GpoAnimationLocked", typeof(bool),
            typeof(ModuleIndicator), new UIPropertyMetadata(true));

    public bool GpoModule {
        get { return (bool)GetValue(GpoModuleProperty); }
        set { SetValue(GpoModuleProperty, value); }
    }
    public static readonly DependencyProperty GpoModuleProperty =
        DependencyProperty.Register("GpoModule", typeof(bool),
            typeof(ModuleIndicator), new UIPropertyMetadata(false, GpoSelectionPropertyChanged));

    protected virtual void GpoSelectionChanged(DependencyPropertyChangedEventArgs e) {
        GpoAnimationLocked = false;
    }
    private static void GpoSelectionPropertyChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) {
        ((ModuleIndicator)sender).GpoSelectionChanged(e);
    }

UserControl xaml(动画的子指标':

    <Viewbox x:Name="GpoIndicator"
             VerticalAlignment="Center"
             HorizontalAlignment="Center"
             Stretch="Fill"
             Width="0"
             Height="0">
        <Grid Height="38"
              Width="38">
            <Ellipse Height="38"
                     Fill="{DynamicResource App.Primary.Light}"
                     Stroke="{DynamicResource App.Border}" />
            <TextBlock Width="38"
                       Height="38"
                       Margin="0"
                       HorizontalAlignment="Left"
                       VerticalAlignment="Top"
                       FontFamily="{DynamicResource AppFont}"
                       FontSize="30"
                       FontWeight="Bold"
                       Foreground="{DynamicResource ResourceKey=App.Accent.Secondary}"
                       Padding="0,2,0,0"
                       Text="G"
                       TextAlignment="Center"
                       TextWrapping="Wrap" />
        </Grid>
        <Viewbox.Style>
            <Style TargetType="Viewbox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}"
                                 Value="True">
                        <DataTrigger.EnterActions>
                            <BeginStoryboard Name="In">
                                <Storyboard>
                                    <StaticResource ResourceKey="SbFadeIn" />
                                </Storyboard>
                            </BeginStoryboard>
                        </DataTrigger.EnterActions>
                        <DataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="In" />
                        </DataTrigger.ExitActions>
                    </DataTrigger>
                    <MultiDataTrigger>
                        <MultiDataTrigger.Conditions>
                            <Condition Binding="{Binding GpoAnimationLocked, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}"
                                       Value="False" />
                            <Condition Binding="{Binding GpoModule, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:ModuleIndicator}}}"
                                       Value="False" />
                        </MultiDataTrigger.Conditions>
                        <MultiDataTrigger.EnterActions>
                            <BeginStoryboard Name="Out">
                                <StaticResource ResourceKey="SbFadeOut" />
                            </BeginStoryboard>
                        </MultiDataTrigger.EnterActions>
                        <MultiDataTrigger.ExitActions>
                            <RemoveStoryboard BeginStoryboardName="Out" />
                        </MultiDataTrigger.ExitActions>
                    </MultiDataTrigger>
                </Style.Triggers>
            </Style>
        </Viewbox.Style>
    </Viewbox>