Popup shows once but not again in WPF animation

I have a window with 4 buttons on the right. When I click on one of the buttons, I want to show 1 of 4 pop-ups. I have only the 1st one, almost finished, but I hit a stumbling block that I cannot understand. Since the 4 pop-ups should have been almost identical, I decided to create a template for the ContentControl , and then set my content in it and put the content control in the pop-up window. One of the elements of my ContentControl template is the close button. I used the storyboard to set the IsOpen property to false. So this part works. (It took a long time to understand ...), but when I press the button again to open the same Popup , it does not appear, and I'm not sure why. Here is my ContentControl 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 really matter, 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 complicated:

 private void brightButton_Click(object sender, RoutedEventArgs e) { popuptest.IsOpen = true; } 

and for good measure there are 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 been working with WPF for about a month now, so if you see something that I have to change, suggest it. Thanks.

+4
source share
1 answer

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

In order to have any practical effect, property animation must take precedence over the base (non-cumulative) value, even if this value has been set locally.

From the same source:

For an animation, the base value can affect the animated value if this animation does not define either From or To for certain behaviors, or if the animation deliberately returns to the base value at completion. To see this in practice, run a sample of From, To, and Animation values. Try setting local rectangle heights in the example so that the initial local value is different from any From in the animation. You will notice that the animation starts immediately with the From values ​​and replaces the base value after starting. An animation can specify to return to the value found before the animation, after it has completed, specifying Stop FillBehavior. Then, the usual priority is used to determine the base value.

Thus, due to this, animations are a priority, however, other sources, such as code notation, will not.

What are the alternatives?

I. As indicated in the documentation, use FillBehavior="Stop" . Since you do not have From , To and Duration animations, this is not an option for you.

II. Use EventTrigger in both cases:

 <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 the code), before setting a new value, delete the animation, for example:

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; } 
+4
source

Source: https://habr.com/ru/post/1498081/


All Articles