【问题标题】:Closing a Popup when its parent gets collapsed当父级折叠时关闭弹出窗口
【发布时间】:2010-10-29 14:29:16
【问题描述】:

我已经为此苦苦挣扎了很长一段时间,但似乎找不到合适的解决方案。这是被剥离的场景。假设您有以下 XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid x:Name="Host" Width="200" Height="200">
        <Popup IsOpen="True">
            <Button Content="Some Button" Click="Button_Click" />
        </Popup>
    </Grid>
</Grid>

Button_Click 事件处理程序中,我所做的只是折叠名称为 Host 的网格。

private void Button_Click(object sender, RoutedEventArgs e)
{
    this.Host.Visibility = System.Windows.Visibility.Collapsed;
}

我所期望的是弹出窗口会关闭因此隐藏按钮。我知道弹出窗口不在同一个 VisualTree 中,并且我理解为什么这可能无法按我期望的方式工作,但是应该有某种机制可以自动发生这种情况。我想到的唯一解决方法是在 LayoutUpdated 上遍历可视树并询问每个 Button 的父级是否可见以及我是否遇到折叠的父级 -> 关闭弹出窗口。然而,想象一下有一个巨大的视觉树的性能冲击。在每个布局通道上遍历可视化树是很疯狂的。 我愿意接受任何形式的建议。

编辑:似乎我没有完全解释我的情况。如果其父级的 ANY 被折叠(不仅仅是直接的),则情况是折叠弹出窗口。在 WPF 中有一个有用的属性称为 IsVisible,它不同于可见性。例如,Visibility 可能仍然是 Visible,但在这种情况下 IsVisible 将是 false

最好的问候, 克

【问题讨论】:

    标签: silverlight layout


    【解决方案1】:

    我认为您在弹出控件中发现了一个错误,或者至少是一个“怪异” - 看看这个:

    我最初的想法是简单地将弹出窗口的可见性绑定到主机。这应该有效。

        <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="Host" Width="200" Height="200" Background="Aqua">
            <Popup IsOpen="True" Visibility="{Binding ElementName=Host, Path=Visibility}" Height="100" Width="100">
                <Button Content="Some Button" Click="Button_Click"/>
            </Popup>
        </Grid>
    </Grid>
    

    但它不起作用。 “主机”网格消失了,但我仍然看到按钮。这让我很困惑,所以我启动了 Silverlight Spy,并检查了这一点 - 设置弹出窗口的可见性并不会隐藏按钮!

    See Demo Video

    无论如何,为了完成这项工作,您只需要稍微调整一下,以便将 Host Visibility 与 IsOpen 属性联系起来。我在这里使用了转换器:

    <UserControl.Resources>
        <Junk:VisibilityToBoolConverter x:Key="VisibilityToBoolConverter"/>
    </UserControl.Resources>
        <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="Host" Width="200" Height="200" Background="Aqua">
            <Popup IsOpen="{Binding ElementName=Host, Path=Visibility, Converter={StaticResource VisibilityToBoolConverter}}" Height="100" Width="100">
                <Button Content="Some Button" Click="Button_Click"/>
            </Popup>
        </Grid>
    </Grid>
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        this.Host.Visibility = System.Windows.Visibility.Collapsed;
    
    }
    
    
    public class VisibilityToBoolConverter : IValueConverter
    {
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return ((Visibility) value) == Visibility.Visible;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    这对我有用。

    【讨论】:

    • 感谢您的回复。实际上,这仅在我折叠 Host 的情况下才有效。但是,如果 Host 本身有一个父级并且我折叠 Host 的父级,则不会发生任何事情。整个问题是我不知道 PopUp 的哪个父级将被折叠。
    • 我不认为你可以,至少,不是你想要的工作方式。它“应该”以这种方式工作,但正如您在视频中看到的那样,即使将 Popup 本身的可见性设置为 Collapsed 也不会隐藏 Popup 的内容。我还尝试将 IsOpen 绑定到 Popup 控件的可见性,但我了解到,将控件的 Parent 属性设置为 Collapsed 不会折叠子控件 - 老实说,不确定它是如何工作的。我认为让这项工作的唯一方法 - 目前 - 是知道父控件是什么,并绑定它。
    【解决方案2】:

    如果你只是想关闭弹出窗口,为什么不将弹出窗口的 IsOpen 设置为 false。

    <Grid x:Name="LayoutRoot" Background="White">
        <Grid x:Name="Host" Width="200" Height="200">
            <Popup x:Name="HostPopup" IsOpen="True">
                <Button Content="Some Button" Click="Button_Click" />
            </Popup>
        </Grid>
    </Grid>
    
    private void Button_Click(object sender, RoutedEventArgs e)
    {
       this.HostPopup.IsOpen = false;
    }
    

    这会关闭弹出窗口。

    【讨论】:

    • 我的主要目标是能够在其任何父项崩溃时关闭弹出窗口。
    • 好吧,对不起,那我的回答不是你需要的。视觉树有多大(有多少用户控件“包装”弹出窗口)?你会为每个包装元素添加某种监听器,如果可见性发生变化,你可以抛出一个事件或进入一个状态......也许你可以对行为或状态做一些事情......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    相关资源
    最近更新 更多