WPF. How to stop data trigger animation through bi

2019-04-19 20:02发布

问题:

In WPF toolkit datagrid I have a data trigger bound to opacity of cell element.

When UpVisibility changes to 1 the path become visible and the animation starts to fade it to 0. Which works.

However my problem now - if I need to prematurely stop/cancel the fading and am setting UpVisibility to 0 the Path is still visible and fading as nothing happened....

How to drop opacity to 0 instantly using MyValue object ?

<Path Data="M 5,0 0,10 10,10" Height="10" Width="10" Fill="Green" Opacity="{Binding MyValue[0].UpVisibility}" Margin="5,0,5,0">
    <Path.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding MyValue[0].UpVisibility}" Value="1.0">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:10" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Path.Style> 
</Path>

回答1:

Have you tried something like this (untested example):

<Path Data="M 5,0 0,10 10,10" Height="10" Width="10" Fill="Green" Opacity="{Binding MyValue[0].UpVisibility}" Margin="5,0,5,0">
    <Path.Style>
        <Style>
            <Style.Triggers>
                <DataTrigger Binding="{Binding MyValue[0].UpVisibility}" Value="1.0">
                    <DataTrigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" From="1.0" To="0.0" Duration="0:0:10" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.EnterActions>
                    <DataTrigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0.0" Duration="0:0:0" />
                            </Storyboard>
                        </BeginStoryboard>
                    </DataTrigger.ExitActions>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Path.Style>
</Path>

I set the animation duration to 0 to be instant. And if you don't define the From property you are instructing WPF to start in the current DependencyProperty value, so it will transition smoothly.



回答2:

Storyboards can also be stopped using the ExitAction on a DataTrigger, which is called when the bound value changes out of the target state. Just give your BeginStoryboard a name, and reference it in a StopStoryboard action, like so:

<DataTrigger.EnterActions>
    <BeginStoryboard Name="your_storyboard_name">
        ...
    </BeginStoryboard>
</DataTrigger.EnterActions>

<DataTrigger.ExitActions>
    <StopStoryboard BeginStoryboardName="your_storyboard_name" />
</DataTrigger.ExitActions>

This may be more appropriate than starting a second storyboard to stop or mask a different storyboard.



回答3:

If you need to reset animation in code behind you usually do such call:

 MyControl.BeginAnimation(OpacityProperty, null);

But how to do it in XAML according to MVVM? Answer is:

<Style>
    <Style.Triggers>
        <DataTrigger Binding="{Binding Vanishing}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard>
                    <Storyboard TargetProperty="Opacity">
                        <DoubleAnimation To="0" Duration="0:0:0.5" FillBehavior="Stop"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.EnterActions>
            <DataTrigger.ExitActions>
                <BeginStoryboard>
                    <Storyboard TargetProperty="Opacity">
                        <DoubleAnimation To="{x:Null}" Duration="0:0:0"/>
                    </Storyboard>
                </BeginStoryboard>
            </DataTrigger.ExitActions>
        </DataTrigger>
    </Style.Triggers>
</Style>

To call animation in ViewModel we can do:

Vanishing = true;
await Task.Delay(500);
Vanishing = false;

Also make sure that binding property (Vanishing in my case) calls INotifyPropertyChanged to notify view about new value