2013-08-20 49 views
4

我有一个窗口,右边有4个按钮。当我点击其中一个按钮时,我想要显示4个弹出窗口中的一个。我只有第一个几乎完成了,但我碰到了一个我似乎无法理解的绊脚石。由于4个弹出窗口需要几乎相同,因此我决定为ContentControl制作一个模板,然后设置我的内容并将内容控件置于弹出窗口中。我的ContentControl模板中的一项是关闭按钮。我用故事板将IsOpen属性设置为false。这部分工作。 (这花了很长时间才发现...)但是当我再次点击按钮打开同样的Popup它不显示,我不知道为什么。这里是我的ContentControl中的模板弹出窗口显示一次,但不是再次显示动画WPF

<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工作了一个月左右,所以如果你看到我应该改变一切的方式来提示它。谢谢。

+1

如果设置AutoReverse = true,会发生什么? –

+0

@GarryVass我对你的魔法一无所知:)我没有提交我的代码,所以我必须等到明天再测试一下你的说法。 –

+0

@GarryVass我把AutoReverse放到我的'BooleanAnimationUsingKeyFrames'中,但没有骰子。我希望有一种方法来调试,看看发生了什么。 –

回答

4

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

为了有任何实际效果,属性的动画必须能够优先于所述基部(动画的)值,即使该值被本地设置。

来自同一来源:

对于一个动画,该基值可以对动画值的效果,如果该动画不会同时指定“发件人”和“To”为特定行为,或者如果动画在完成时故意恢复到基值。要在实践中看到此情况,请运行From,To和By Animation Target Values Sample。尝试在示例中设置矩形高度的局部值,使得初始局部值与动画中的任何“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; 
}  
+1

我做了一个UserControl,然后将其从UserControl更改为Popup,添加了我的矩形,按钮和内容演示者。制作了一种方法来设置内容演示者的子项。我使用后面的代码关闭弹出窗口。但这些信息对未来非常有用,因为我可能最终会再次这样做。感谢您对此的勤奋研究。 –