我有一个窗口,右边有4个按钮。当我点击其中一个按钮时,我想要显示4个弹出窗口中的一个。我刚刚完成了第一个,但我遇到了一个我似乎无法弄清楚的绊脚石。由于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合作了大约一个月,所以如果你看到我应该改变的东西,建议它。谢谢。
答案 0 :(得分:4)
当动画用于特定属性时,由于优先级列表(link),只能通过动画进一步分配属性。引自MSDN
:
为了产生任何实际效果,属性的动画必须能够优先于基础(非动画)值,即使该值是在本地设置的。
来自同一来源:
对于动画,如果动画未对某些行为同时指定“From”和“To”,或者动画在完成时故意恢复为基值,则基值可能会对动画值产生影响。要在实践中查看此内容,请运行“从”,“到”和“按动画目标值”示例。尝试在示例中设置矩形高度的本地值,以使初始本地值与动画中的任何“From”不同。您将注意到,动画会立即使用“From”值开始,并在启动后替换基值。动画可以指定在动画完成后通过指定Stop FillBehavior返回到动画之前找到的值。然后,正常优先级用于基值确定。
因此,由于这一点,动画的属性是第一优先,但是其他来源,例如代码,指定不会。
有哪些替代方案?
I.
如文档中所述,请使用FillBehavior="Stop"
。由于您没有动画From
,To
和Duration
,因此您无法选择。
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;
}