0

My problem seems to be the opposite of the one everybody else has. My WPF DataTrigger fires sometimes even when the viewmodel property to which it is tied does not change. I've put logging code in the property itself to make sure it's not changing.

Is there some easy to way determine WHY an animation is firing? Some event I can subscribe to let me put a breakpoint in my own code and look at the call stack at the moment the animation fires?

Here's the Storyboard. Just animating a double from 0 to 1 over 1 second. The double will be stored in FrameworkElement.Tag

<Storyboard x:Key="TagZeroToOne" x:Shared="False">
    <DoubleAnimation Storyboard.TargetProperty="Tag" From="0" To="1" Duration="0:0:1.0" />
</Storyboard>

And here is the relevant bit of the style that uses it in the DataTrigger. (I've left out the item template and panel)

<!-- Style for ItemsControl that draws circular handles when ShapeVm is selected -->

<Style x:Key="ShapeHandlesItemsControlStyle" TargetType="{x:Type ItemsControl}">

    <d:Style.DataContext>
        <x:Type Type="gci:ShapeVm" />
    </d:Style.DataContext>

    <!-- Default style value of ItemsControl.Tag" property is 1.0 -->

    <Setter Property="Tag">
        <Setter.Value>
            <sys:Double>1.0</sys:Double>
        </Setter.Value>
    </Setter>

    <!--
    We cannot animate Opacity directly because its max value depends upon
    a binding but we be we can make it be dependent upon another property
    "Tag" that we *do* animate.  This requires a Math Converter as well
    Picked up this technique from the following SO question

    https://stackoverflow.com/questions/2186933/wpf-animation-binding-to-the-to-attribute-of-storyboard-animation/14164245#14164245

    -->
    <Setter Property="Opacity">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource CvtMath}" 
                          ConverterParameter="1.0 - (x *(1.0-y))">            <!--  Calculation  -->
                <Binding Path="Tag" RelativeSource="{RelativeSource Self}" /> <!--  Animated operand (0.0 to 1.0)  -->
                <Binding ElementName="Root" Path="ShapeHandleOpacity" />      <!--  Configured opacity operand  -->
            </MultiBinding>
        </Setter.Value>
    </Setter>



    <!-- When ShapeVm.IsSelected becomes true, animate the ItemsControl.Tag from 0 to 1.0 -->

    <Style.Triggers>

        <DataTrigger Binding="{Binding IsSelected}" Value="True">
            <DataTrigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource TagZeroToOne}" />
            </DataTrigger.EnterActions>
        </DataTrigger>

    </Style.Triggers>

The idea is that when the user first selects the shape, my code-behind sets its IsSelected property to "true". That makes the animation fire and I see the visual effect tied to my animation. But that's supposed to be it.

Instead, it seems that almost every other time I click on the object in question, The animation fires and I see the effect. Yet I have verified (repeatedly) via logging and breakpoints that the IsSelected property is never changing after that. Nobody is setting it. Nobody is firing a PropertyChanged Notification for it and as far as I can see, nobody is even firing PropertyChanged(null).

And here is the ShapeVm.IsSelected property

private bool _isSelected;
public bool IsSelected
{
    get => _isSelected;
    set
    {
        if (value == _isSelected)
            return;

        _isSelected = value;
        Debug.WriteLine($"Shape selected change to {value}");
    }
}

So how do I determine why WPF is making this trigger fire?

Joe
  • 5,394
  • 3
  • 23
  • 54
  • You say the animation keeps firing, but your code above is only changing the `Tag` property value, which has no visual effect. Therefore I'm presuming you have some other kind of trigger tied into the `Tag` value in order to get the visual changes. If so, are you certain nothing else is changing the value of the `Tag` property? – Steven Rands Sep 18 '20 at 13:34
  • Hi Stephen, I did not include the XAML that shows how how the animation of Tag produces a visual effect because it was extremely verbose and irrelevant to the fact that the animation was, indeed firing. That datatrigger is the only trigger for the animation so I do know it is firing. I can edit my post include it if you think it will help. I mostly was hoping for advice on how to hook into the animation process to see why it is firing. – Joe Sep 18 '20 at 20:03
  • I've added in the Opacity binding that is the visual effect I described. It's pretty complicated as it uses an indirect binding technique I actually picked up here on SO. We cannot animate opacity directly because the max allowable opacity must also be bound and animations don't like such Bindings. But we can animate Tag and make Opacity bind to that. I've put the link to the SO question that describes this in the code. – Joe Sep 18 '20 at 20:11
  • It seems like you have some sort of ItemsControl with shapes in it, but your IsSelected property binding looks like it is part of the ItemsControl's style which doesn't sound right. Is that how it is supposed to work? – Steven Rands Sep 21 '20 at 08:39
  • 2
    You could try to use a converter with the `Tag` property and set a breakpoint in the `Convert` method. See this: https://spin.atomicobject.com/2013/12/11/wpf-data-binding-debug/ – FredM Sep 21 '20 at 10:37

0 Answers0