Popup shows once but not again in animation WPF

animation, c#, popup, wpf

Solution

When the animation is used for a particular property, thanks to the precedence list (link), the further assignment to property is only possible through animation. Quote from `MSDN`:

In order to have any practical effect, an animation of a property must be able to have precedence over the base (unanimated) value, even if that value was set locally.

From the same source:

For an animation, the base value can have an effect on the animated value, if that animation does not specify both "From" and "To" for certain behaviors, or if the animation deliberately reverts to the base value when completed. To see this in practice, run the From, To, and By Animation Target Values Sample. Try setting the local values of the rectangle height in the example, such that the initial local value differs from any "From" in the animation. You will note that the animations start right away using the "From" values and replace the base value once started. The animation might specify to return to the value found before animation once it is completed by specifying the Stop FillBehavior. Afterwards, normal precedence is used for the base value determination.

Thus, because of this the properties of animation is a first priority, however other sources, such as a code, designate will not.

What are the alternatives?

`I.` As stated in the documentation, use the `FillBehavior="Stop"`. Since you have there is no in animation `From`, `To` and `Duration`, for you this is not an option.

`II.` Use `EventTrigger` in both cases, that is:

<EventTrigger SourceName="CloseButton" RoutedEvent="Button.Click">
    <BeginStoryboard>
        <Storyboard>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="MyPopup"
                                                    Storyboard.TargetProperty="(Popup.IsOpen)" 
                                                    Duration="0:0:0">

                <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

<EventTrigger SourceName="OpenButton" RoutedEvent="Button.Click">
    <BeginStoryboard>
        <Storyboard>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="MyPopup"
                                                    Storyboard.TargetProperty="(Popup.IsOpen)" 
                                                    Duration="0:0:0">

                <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
            </BooleanAnimationUsingKeyFrames>
        </Storyboard>
    </BeginStoryboard>
</EventTrigger>

`III.` In the handler (in code), before setting new value, remove the animation, like this:

`XAML`

<Grid>
    <Grid.Triggers>
        <EventTrigger SourceName="CloseButton" RoutedEvent="Button.Click">
            <BeginStoryboard>
                <Storyboard>
                    <BooleanAnimationUsingKeyFrames Storyboard.TargetName="MyPopup"
                                                    Storyboard.TargetProperty="(Popup.IsOpen)" 
                                                    Duration="0:0:0">

                        <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" />
                    </BooleanAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Grid.Triggers>

    <Popup x:Name="MyPopup" Width="200" Height="200" IsOpen="True">
        <Grid Background="Azure">
            <Label Content="Test label" />
        </Grid>
    </Popup>

    <Button Name="OpenButton" Content="OpenButtonFromCode" Width="140" Height="30" Click="OpenButton_Click" />
    <Button Name="CloseButton" Content="CloseButtonfromEventTrigger" Width="180" Height="30" Margin="0,80,0,0" />
</Grid>

`Code behind`

private void OpenButton_Click(object sender, RoutedEventArgs e)
{
    MyPopup.BeginAnimation(Popup.IsOpenProperty, null);
    MyPopup.IsOpen = true;
}     

Problem

I have a window that has 4 buttons on the right. When I click on one of the buttons I want 1 of 4 popups to show. I've only got the 1st one almost done, but I've hit a stumbling block that I can't seem to figure out. Since the 4 popups needed to be almost identical I decided to make a template for a `ContentControl` then set my content in that and put the content control in the popup. One of the items in my ContentControl's template is a close button. I used a storyboard to set the `IsOpen` property to false. So that part works. (That took a long time to figure out...) but When I click on the button again to open up that same `Popup` it doesn't show, and I'm not sure why. Here is my ContentControl's Template ``` <Style x:Key="PopupContentStyle" TargetType="ContentControl"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="ContentControl"> <Grid> <Rectangle Fill="WhiteSmoke" Opacity=".50" Width="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=Width}" Height="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}, Path=Height}" /> <Button Height="50" Style="{DynamicResource CloseButton}" HorizontalAlignment="Right" VerticalAlignment="Top" > <Button.Triggers> <EventTrigger RoutedEvent="Button.Click"> <BeginStoryboard> <Storyboard> <BooleanAnimationUsingKeyFrames Storyboard.Target="{Binding RelativeSource={RelativeSource AncestorLevel=1, AncestorType=Popup,Mode=FindAncestor}}" Storyboard.TargetProperty="(Popup.IsOpen)" Duration="0:0:0"> <DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="False" /> </BooleanAnimationUsingKeyFrames> </Storyboard> </BeginStoryboard> </EventTrigger> </Button.Triggers> </Button> <ContentPresenter /> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style> ``` although it doesn't matter too much here is my `Popup` style: ``` <Style x:Key="PopupStyle" TargetType="{x:Type Popup}"> <Setter Property="AllowsTransparency" Value="True"/> <Setter Property="PopupAnimation" Value="Fade"/> <Setter Property="Placement" Value="Center"/> <Setter Property="PlacementTarget" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}"/> </Style> ``` In my `UserControl` I have this `Popup`: ``` <Popup x:Name="popuptest" Opened="popuptest_Opened" Closed="popuptest_Opened" Style="{DynamicResource PopupStyle}" > <ContentControl Style="{DynamicResource PopupContentStyle}"> <b:BrightnessControl /> </ContentControl> </Popup> ``` The code I use to open it for the brightness button is not complex: ``` private void brightButton_Click(object sender, RoutedEventArgs e) { popuptest.IsOpen = true; } ``` and for good measure here is the other 2 events from my xaml ``` public event PopupIsOpenedChangedHandler PopupIsOpenedChanged; public delegate void PopupIsOpenedChangedHandler(bool isOpen); private void OnPopupIsOpenedChanged(bool isOpen) { if (PopupIsOpenedChanged != null) PopupIsOpenedChanged(isOpen); } private void popuptest_Opened(object sender, System.EventArgs e) { OnPopupIsOpenedChanged(popuptest.IsOpen); } ``` Please help :). Oh and I've only been working with WPF for about a month now, so if you see something that I should change by all means suggest it. Thank you.

Original source