UWP XAML 弹出窗口不遵守 VerticalAlignment?

UWP XAML Popup not respecting VerticalAlignment?

我正在尝试将 Windows Store/UWP 应用程序中的弹出窗口居中。

简而言之,我正在使用 MainPage 并添加...

Button_Click 调用 _centerPopup,它试图使 Popup 居中,然后将 IsOpen 设置为 true。我无法让它工作。

private void _centerPopup(Popup popup, Border popupBorder, FrameworkElement extraElement = null)
{
    double ratio = .9; // How much of the window the popup fills, give or take. (90%)

    Panel pnl = (Panel)popup.Parent;
    double parentHeight = pnl.ActualHeight;
    double parentWidth = pnl.ActualWidth;

    // Min 200 for each dimension.
    double width = parentWidth * ratio > 200 ? parentWidth * ratio : 200;
    double height = parentHeight * ratio > 200 ? parentHeight * ratio : 200;

    popup.Width = width;
    popup.Height = height;

    //popup.HorizontalAlignment = HorizontalAlignment.Center;
    popup.VerticalAlignment = VerticalAlignment.Top;    // <<< This is ignored?!

    // Resize the border too. Not sure how to get this "for free".
    popupBorder.Width = width;
    popupBorder.Height = height;

    // Not using this here, but if there's anything else that needs resizing, do it.
    if (null != extraElement)
    {
        extraElement.Width = width;
        extraElement.Height = height;
    }
}

如果我不尝试在 Button_Click 中调整弹出窗口的大小和居中,这就是我在单击“单击我”后得到的...

private void Button_Click(object sender, RoutedEventArgs e)
{
    //_centerPopup(this.popupTest, this.popupTestBorder);
    this.popupTest.IsOpen = true;
}

如果我取消对 _centerPopup 的调用的注释,我会得到这个,弹出窗口位于 按钮下方:

private void Button_Click(object sender, RoutedEventArgs e)
{
    _centerPopup(this.popupTest, this.popupTestBorder);
    this.popupTest.IsOpen = true;
}

那可不行。我 thought popup.VerticalAlignment = VerticalAlignment.Top; 会解决这个问题。

FrameworkElement.VerticalAlignment Property

Gets or sets the vertical alignment characteristics applied to this element when it is composed within a parent element such as a panel or items control.


将 Popup 移动到 StackPanel 的顶部?

奇怪的是,如果我将 Popup 移到 StackPanel 的顶部,它实际上会在显示后将其他控件向下推。

单击“单击我”没有 _centerPopup:

看起来很有希望!它很好地悬浮在其他控件之上,关闭后对布局没有明显影响。

但是添加回来 _centerPopup,即使在将设置 VerticalAlignment 注释掉到 Top 之后,事情也会死得很惨烈。

看起来很完美直到您注意到所有其他控件都被按下。 ???这里是点击“点击关闭”之后:

其他控件永久下推。为什么会这样?弹出窗口不应该像我调整大小之前那样浮动吗?


完整来源

XAML

<Page
    x:Class="PopupPlay.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PopupPlay"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Name="StackMain">
        <TextBlock>
            This is some text<LineBreak />
            This is some text<LineBreak />
            This is some text<LineBreak />
            This is some text<LineBreak />
        </TextBlock>
        <Button Click="Button_Click" Content="Click Me"></Button>

        <Popup x:Name="popupTest">
            <Border
                    Name="popupTestBorder"
                    Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
                    BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
                    BorderThickness="2">
                <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                    <TextBlock Name="txtPopup"
                               Text="This is some text"
                               FontSize="24"
                               HorizontalAlignment="Center" />
                    <Button Name="btnClose"
                            Click="btnClose_Click"
                               Content="Click to close"></Button>
                </StackPanel>
            </Border>
        </Popup>
    </StackPanel>
</Page>

完整MainPage.xaml.cs代码

using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;

namespace PopupPlay
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _centerPopup(this.popupTest, this.popupTestBorder);

            this.popupTest.IsOpen = true;
        }

        private void _centerPopup(Popup popup, Border popupBorder, FrameworkElement extraElement = null)
        {
            double ratio = .9; // How much of the window the popup fills, give or take. (90%)
    
            Panel pnl = (Panel)popup.Parent;
            double parentHeight = pnl.ActualHeight;
            double parentWidth = pnl.ActualWidth;
    
            // Min 200 for each dimension.
            double width = parentWidth * ratio > 200 ? parentWidth * ratio : 200;
            double height = parentHeight * ratio > 200 ? parentHeight * ratio : 200;
    
            popup.Width = width;
            popup.Height = height;
    
            //popup.HorizontalAlignment = HorizontalAlignment.Center;
            popup.VerticalAlignment = VerticalAlignment.Top;    // <<< This is ignored?!
    
            // Resize the border too. Not sure how to get this "for free".
            popupBorder.Width = width;
            popupBorder.Height = height;
    
            // Not using this here, but if there's anything else that needs resizing, do it.
            if (null != extraElement)
            {
                extraElement.Width = width;
                extraElement.Height = height;
            }
        }

        private void btnClose_Click(object sender, RoutedEventArgs e)
        {
            this.popupTest.IsOpen = false;
        }
    }
}

有几个问题似乎相关。我看不到可行的修复方法。 (注意:这些并不是所有 UWP 特定的。)

痛苦的是,同样的设置在另一个应用程序中对我有用,当它被定位在一个带有 Pivot 的更复杂的网格中时,但我看到 pivots are buggy

Wpf 的 Placement 内容 sounds promising,但在 UWP 领域中不存在。

尝试如下更改您的 xaml...

<Page...>
    <Grid x:Name="LayoutRoot">
        <Popup>
        </Popup>

        <Grid x:Name="ContentPanel">
        </Grid>
    </Grid>
</Page>

因此,将 Popup 控件移到内容区域之外,并将包含所有内容的 stacklayout 放在 ContentPanel Grid 中(如上面的代码示例所示)

应该停止将其他控件向下推...

您的 Popup 在垂直 StackPanel 内,这意味着 StackPanel 会将弹出窗口与面板的其他子元素并排放置,这就是它向下推的原因文本。

此外,VerticalAlignment 被面板忽略,因为面板为弹出窗口的大小分配了足够的垂直 space,因此没有空间让它垂直对齐弹出窗口space 它被分配了。

我建议使用 Grid 作为 Page 的根元素,并将 StackPanelPopup 直接放在 Grid 中,像这样:

<Grid>
    <StackPanel Name="StackMain">
        <TextBlock>
        This is some text<LineBreak />
        This is some text<LineBreak />
        This is some text<LineBreak />
        This is some text<LineBreak />
        </TextBlock>
        <Button Click="Button_Click" Content="Click Me"></Button>
    </StackPanel>
    <Popup x:Name="popupTest">
        <Border
                Name="popupTestBorder"
                Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
                BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
                BorderThickness="2">
            <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
                <TextBlock Name="txtPopup"
                           Text="This is some text"
                           FontSize="24"
                           HorizontalAlignment="Center" />
                <Button Name="btnClose"
                        Click="btnClose_Click"
                           Content="Click to close"></Button>
            </StackPanel>
        </Border>
    </Popup>
</Grid>

Grids 适用于此目的,当您希望拥有重叠元素或多个不影响任何其他子元素的位置和大小的元素时。您希望弹出窗口的布局与堆栈面板及其子项的布局分开,因此您应该这样组织 XAML。