I'm trying to center a Popup in a Windows Store/UWP app.
In brief, I'm taking MainPage and adding...
- A
TextBlock
with some text - A
Button
with an event handler,Button_Click
- A
Popup
namedpopupTest
. It contains...- A
Border
with...- A
StackPanel
with- A
TextBlock
- A
Button
. ThisButton
's event handle sets thePopup
'sIsOpen
to false.
- A
- A
- A
Button_Click
calls _centerPopup
, which tries to center the Popup
and then sets IsOpen
to true
. I can't get this to work.
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;
}
}
If I don't try to resize and center the Popup in Button_Click, here's what I get after clicking "Click Me"...
private void Button_Click(object sender, RoutedEventArgs e)
{
//_centerPopup(this.popupTest, this.popupTestBorder);
this.popupTest.IsOpen = true;
}
If I uncomment out the call to _centerPopup
, I get this, with the popup staying under the button:
private void Button_Click(object sender, RoutedEventArgs e)
{
_centerPopup(this.popupTest, this.popupTestBorder);
this.popupTest.IsOpen = true;
}
That's no good. I thought popup.VerticalAlignment = VerticalAlignment.Top;
would've fixed that.
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.
Move Popup to top of StackPanel?
Strangely, if I move the Popup up to the top of my StackPanel, it actually pushes the other controls down after being shown.
Clicking "Click Me" without _centerPopup
:
That looks promising! It's floating over the other controls nicely, and there's no obvious impact to the layout after it's closed.
But add back _centerPopup
, even after commenting out setting VerticalAlignment
to Top
, and things die a horrible, fiery death.
It looks perfect until you notice that every other control was pushed down. ??? Here's after clicking "Click to close":
Other controls are pushed down permanently. Why does that happen? Shouldn't the popup float like it did before I resized it?
Full Source
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>
Full MainPage.xaml.cs code
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;
}
}
}
There are several questions that seem related. I do not see a viable fix. (Note: These are not all UWP specific.)
- Center Popup in XAML
- Place Popup at top right corner of a window in XAML
- How to set vertical offset for popup having variable height
Painfully, this same setup is working for me in another app when it's positioned in a much more complicated grid with a Pivot, but I see that pivots are buggy.
Wpf's Placement
stuff sounds promising, but doesn't exist in UWP-land.