Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to center a popup in window (Windows store apps)

I have a custom popup (as a user control) which I load programatically. I'm not able to center it on x axis, only on vertical. The popup is not added onto an xaml file, but it is added on the root window.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using System.Windows;
using Windows.UI.Core;

// The User Control item template is documented at http://go.microsoft.com/fwlink/?LinkId=234236

namespace QSTLibrary.WIN8.Tools
{
    public sealed partial class CustomProgressRingPopup : UserControl
    {

        public CustomProgressRingPopup()
        {
            this.InitializeComponent();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
                        "Text", 
                        typeof(string), 
                        typeof(CustomProgressRingPopup),
                        new PropertyMetadata("", OnTextChanged));


        public void OpenPopup()
        {
            this.ParentPopup.IsOpen = true;
        }

        public void ClosePopup()
        {
            this.ParentPopup.IsOpen = false;
        }

        private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var instance = d as CustomProgressRingPopup;
            var newValue = e.NewValue as string;
            if (instance != null && newValue != null)
            {
                instance.CustomTextBlock.Text = newValue;
            }
        }

        private void OnPopupLoaded(object sender, RoutedEventArgs e)
        {
            this.ParentPopup.HorizontalOffset = (Window.Current.Bounds.Width - gdChild.ActualWidth) / 2;
            this.ParentPopup.VerticalOffset = (Window.Current.Bounds.Height - gdChild.ActualHeight) / 2;
        }
    }
}

userControl xaml:

<UserControl
    x:Class="QSTLibrary.WIN8.Tools.CustomProgressRingPopup"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:QSTLibrary.WIN8.Tools"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300"
    d:DesignWidth="400">

    <Popup x:Name="ParentPopup" HorizontalAlignment="Center" VerticalAlignment="Center" Loaded="OnPopupLoaded">
        <Grid x:Name="gdChild" Height="auto" Width="auto" Background="Blue" Margin="20">
            <Grid.RowDefinitions>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <ProgressRing x:Name="CustomProgressRing" Height="40" Width="40" IsActive="true" Grid.Column="0" Margin="20"/>
            <TextBlock x:Name="CustomTextBlock" Height="auto" Width="auto" FontSize="25" Grid.Column="1" Margin="20"/>
        </Grid>
    </Popup>    
</UserControl>

Here is how I use it external:

_loginProgressRingPopup.Text = "Logging in";
_loginProgressRingPopup.OpenPopup();
like image 804
Alexandru Circus Avatar asked Sep 26 '13 15:09

Alexandru Circus


1 Answers

Positioning a Popup in a UWP Windows Store app is not as straightforward as it could be. Here is how I ended up solving it. Rather than observing the LayoutUpdated event (which can cause a layout cycle), observe the SizeChanged event of the top-level element of your view and use this to reposition the popup it is contained within.

In my case I am positioning the dialog in the center of the window, and thus use Window.Current. You also need to convert the coordinates, because the popup will use its own relative coordinate system based on where the Popup element is actually defined in your layout:

private void MyDialog_SizeChanged(object sender, SizeChangedEventArgs e) {
    var transform = Window.Current.Content.TransformToVisual(_popup);
    Point point = transform.TransformPoint(new Point(0, 0)); // gets the window's (0,0) coordinate relative to the popup

    double hOffset = (Window.Current.Bounds.Width - this.ActualWidth) / 2;
    double vOffset = (Window.Current.Bounds.Height - this.ActualHeight) / 2;

    _popup.HorizontalOffset = point.X + hOffset;
    _popup.VerticalOffset = point.Y + vOffset;
}
like image 187
devios1 Avatar answered Oct 14 '22 00:10

devios1