【问题标题】:Popup shows once but not again in animation WPF弹出窗口在动画 WPF 中显示一次但不再显示
【发布时间】:2013-08-23 02:02:17
【问题描述】:

我有一个右侧有 4 个按钮的窗口。当我单击其中一个按钮时,我希望显示 4 个弹出窗口中的 1 个。我只完成了第一个几乎完成的任务,但我遇到了一个我似乎无法弄清楚的绊脚石。由于 4 个弹出窗口需要几乎相同,我决定为 ContentControl 创建一个模板,然后在其中设置我的内容并将内容控件放在弹出窗口中。我的 ContentControl 模板中的一项是关闭按钮。我使用故事板将IsOpen 属性设置为false。所以那部分有效。 (这花了很长时间才弄清楚...)但是当我再次单击该按钮以打开相同的Popup 时,它没有显示,我不知道为什么。这是我的 ContentControl 的模板

<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>

虽然没关系这里是我的Popup风格:

<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>

在我的UserControl 我有这个Popup

<Popup x:Name="popuptest" Opened="popuptest_Opened" Closed="popuptest_Opened" Style="{DynamicResource PopupStyle}" >
    <ContentControl Style="{DynamicResource PopupContentStyle}">
        <b:BrightnessControl />
    </ContentControl>
</Popup>

我用来打开亮度按钮的代码并不复杂:

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

这里是我的 xaml 中的其他 2 个事件

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);
}

请帮忙:)。哦,我现在才使用 WPF 大约一个月,所以如果你看到一些我应该改变的东西,一定要建议它。谢谢。

【问题讨论】:

  • 如果设置 AutoReverse = true 会发生什么?
  • @GarryVass 我对你的魔法一无所知 :) 我没有提交我的代码,所以我必须等到明天才能测试你所说的内容。
  • @GarryVass 我将 AutoReverse 放入我的 BooleanAnimationUsingKeyFrames 但没有骰子。我希望有办法对此进行调试,看看发生了什么。

标签: c# wpf animation popup


【解决方案1】:

当动画用于特定属性时,由于优先级列表 (link),只能通过动画进一步分配给属性。引用MSDN:

为了产生任何实际效果,属性的动画必须能够优先于基本(非动画)值,即使该值是在本地设置的。

来自同一来源:

对于动画,如果该动画没有为某些行为指定“From”和“To”,或者如果动画在完成时故意恢复为基本值,则基值会对动画值产生影响。要在实践中看到这一点,请运行 From、To 和 By Animation Target Values 示例。尝试在示例中设置矩形高度的局部值,使初始局部值不同于动画中的任何“From”。您会注意到动画使用“From”值立即开始,并在开始后替换基本值。通过指定 Stop FillBehavior,动画可能会指定在动画完成后返回到动画之前找到的值。之后,正常优先级用于确定基值。

因此,因此动画的属性是第一要务,但其他来源(例如代码)不会指定。

有什么选择?

I. 如文档中所述,使用FillBehavior="Stop"。由于您在动画中没有FromToDuration,所以这不是您的选择。

II. 在这两种情况下都使用EventTrigger,即:

<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. 在处理程序中(在代码中),在设置新值之前,删除动画,如下所示:

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;
}     

【讨论】:

  • 我最终制作了一个 UserControl,然后将其从 UserControl 更改为 Popup,添加了我的矩形、按钮和内容演示器。制作了一种方法来设置 Content Presenter 的子项。我使用后面的代码来关闭弹出窗口。但这些信息对未来非常有用,因为我可能最终会再次这样做。感谢您对此的辛勤研究。
猜你喜欢
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-10
  • 1970-01-01
相关资源
最近更新 更多