Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当父窗口折叠时,如何关闭弹出窗口? 背景_C#_Wpf_Popup - Fatal编程技术网

C# 当父窗口折叠时,如何关闭弹出窗口? 背景

C# 当父窗口折叠时,如何关闭弹出窗口? 背景,c#,wpf,popup,C#,Wpf,Popup,我有一个HeaderedContentControl的控件模板,其中包含一个作为标题的按钮,单击时会打开一个包含主要内容的弹出窗口(通过EventTrigger) 这和我预期的一样,直到我尝试在弹出窗口中添加一个按钮以折叠控件。主按钮(标题)消失,但弹出窗口(内容)保持在原来的位置,直到我(通过单击某个地方)从中获取鼠标焦点 下面是一个简短的示例,演示了该问题: 在我的真实代码中,ControlTemplate与控件的用法不在同一位置。它完全在另一个地方的ResourceDictionary

我有一个
HeaderedContentControl
的控件模板,其中包含一个作为标题的按钮,单击时会打开一个包含主要内容的弹出窗口(通过
EventTrigger

这和我预期的一样,直到我尝试在弹出窗口中添加一个按钮以折叠控件。主按钮(标题)消失,但弹出窗口(内容)保持在原来的位置,直到我(通过单击某个地方)从中获取鼠标焦点

下面是一个简短的示例,演示了该问题:


在我的真实代码中,
ControlTemplate
与控件的用法不在同一位置。它完全在另一个地方的
ResourceDictionary
中,不应该知道它弹出窗口的任何内容-它直接将它传递给
ContentPresenter

问题: 理想情况下,是否有一种方法可以在不让
ControlTemplate
知道弹出窗口包含“隐藏”按钮的可能性的情况下,在
HeaderedContentControl
折叠时使弹出窗口消失

我试过的
  • 将另一个触发器添加到
    HeaderedContentControl
    以监视
    是否可见
    更改。没有合适的
    EventTrigger
    ,其他触发器不能包含元素名称
  • HeaderedContentControl
    的子类中将事件处理程序添加到
    IsVisibleChanged
    。事件将触发,但设置为
    false
    后,IsOpen仍保持
    true

    • 这里的基本问题是,您正在使用
      情节提要来控制弹出状态。这意味着当发生
      单击
      事件时,您正在告诉WPF开始一个动画,在该动画中,它将弹出窗口的
      IsOpen
      属性设置为
      true

      请注意,动画没有固定的持续时间,因此实际上从不停止。尝试将
      Popup.IsOpen
      设置为
      false
      失败,因为WPF仍在为属性设置动画,因此会立即将其设置回“true”

      作为概念证明,请尝试在启动动画后立即暂停动画:

      <EventTrigger RoutedEvent="Button.Click" >
        <BeginStoryboard Name="ShowPopupStoryBoard">
          <Storyboard>
            <BooleanAnimationUsingKeyFrames Storyboard.TargetName="Popup"
                                  Storyboard.TargetProperty="(Popup.IsOpen)" >
              <DiscreteBooleanKeyFrame KeyTime="0" Value="True" />
            </BooleanAnimationUsingKeyFrames>
          </Storyboard>
        </BeginStoryboard>
        <PauseStoryboard BeginStoryboardName="ShowPopupStoryBoard"/>
      </EventTrigger>
      
      
      
      通过暂停动画,可以防止WPF重置
      Popup.IsOpen
      属性。因此,您可以继续并对
      IsVisibleChanged
      (或其他适当的事件)做出反应,设置
      Popup.IsOpen
      属性
      false
      ,并使其实际生效

      不幸的是,这只会暂停动画。在重复测试中,上述方法并不一致——也就是说,它总是在第一次单击时起作用,但在随后的单击中(我更改了演示代码以不隐藏按钮),有时起作用,有时不起作用——我认为这是与调用各种
      EventTrigger
      子级有关的时间问题

      在任何情况下,
      情节提要
      似乎都是一个沉重的负担,至少在某些明显的方面,显示弹出窗口的机制不合适。我知道的一个持续工作的替代方法是,只需将事件处理程序添加到模板的
      按钮
      控件的
      单击
      事件,然后将
      Popup.IsOpen
      属性设置为
      true
      。在这种情况下,您只需对其进行切换,而不是对其设置动画,因此WPF不会做任何事情来强制它在稍后将其设置回
      false
      时保持设置为
      true

      不过,最重要的是要在可用的机制中选择某种机制,以确保
      Popup.IsOpen
      属性不会持续被设置动画。只要WPF将属性动画设置为
      true
      值,将其设置为
      false
      就不会有任何效果(的确,弹出窗口消失有点令人惊讶,即使它失去焦点……我猜缺少焦点比
      IsOpen
      属性值更重要)


      不幸的是,因为这里的主要问题与模板的当前实现有关,我认为与您声明的偏好相反,任何正确的修复都需要您修改模板。我想你可以在弹出窗口的内容对象中添加逻辑来追踪它的故事板并实际阻止它。但在这种情况下,治疗似乎比疾病更糟糕。

      它可能不符合您的要求,但我想我更喜欢约翰·梅尔维尔的方法:。没有故事板,更简单的绑定。太棒了-我没有想到动画会造成问题。在阅读您的答案时,我意识到我对不修改模板的限制有点过度。我的意思是,我不想在模板中添加任何特定于“隐藏”按钮的内容,但添加一对事件处理程序,以便在单击时打开,在不可见时关闭是可以的。谢谢你非常详尽的回答!