5

I have created a Popup by using the following code, but I can not figure out how to center it
I tried to automatically change the margin on runtime, but I could not figure out how to do it, but do anybody has an idea of how to center the popup?
It does not has a standard-dimension cause I need to globalize my program

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" Name="MainGrid">
   <Popup x:Uid="LoginPopup" IsOpen="True" Name="LoginPopup">
      <Grid>
         <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto" />
         </Grid.RowDefinitions>
         <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="*" />
         </Grid.ColumnDefinitions>
         <TextBlock Margin="10" Grid.Column="0" Grid.Row="0" Text="App Name" Grid.ColumnSpan="2" Style="{StaticResource HeaderTextStyle}" />
         <TextBlock Margin="10" Grid.Column="0" Grid.Row="1" Text="Username" Style="{StaticResource ResourceKey=SubheaderTextStyle}" />
         <TextBox Margin="10" Grid.Column="1" Grid.Row="1" Name="InputUsername" />
         <TextBlock Margin="10" Grid.Column="0" Grid.Row="2" Text="Password" Style="{StaticResource ResourceKey=SubheaderTextStyle}" />
         <PasswordBox Margin="10" Grid.Column="1" Grid.Row="2" Name="InputPassword" />
         <StackPanel  Margin="10" Grid.Column="1" Grid.Row="3" HorizontalAlignment="Left" Orientation="Horizontal">
            <Button Name="Login"  x:Uid="LoginPopupLogin"  />
            <Button Name="Cancel" x:Uid="LoginPopupCancel" />
         </StackPanel>
      </Grid>
   </Popup>
</Grid>

UPDATE

I tried with user1603313's answer below, but it did not do the trick, as it says the size of the grid inside the popup is NaN.
I also tried to move the method into the grid, but it didn't do the trick either
The method I am talking about is this with the grid updated properly

private void LoginPopup_Loaded_1(object sender, RoutedEventArgs e)
{
   LoginPopup.HorizontalOffset = (Window.Current.Bounds.Width - gdChild.ActualWidth) / 2;
   LoginPopup.VerticalOffset = (Window.Current.Bounds.Height - gdChild.ActualHeight) / 2;
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
The87Boy
  • 877
  • 4
  • 14
  • 32

3 Answers3

9

Here's a solution to you problem. i am rewriting the xaml code and along with the modification and you can find the explanation after the code.

     <Popup x:Uid="LoginPopup" IsOpen="True" Name="LoginPopup" Loaded="LoginPopup_Loaded_1">
        <Grid Background="Red" x:Name="gdChild" Height="Auto" Width="Auto">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <TextBlock Margin="10" Grid.Column="0" Grid.Row="0" Text="App Name" Grid.ColumnSpan="2" Style="{StaticResource HeaderTextStyle}" />
            <TextBlock Margin="10" Grid.Column="0" Grid.Row="1" Text="Username" Style="{StaticResource ResourceKey=SubheaderTextStyle}" />
            <TextBox Margin="10" Grid.Column="1" Grid.Row="1" Name="InputUsername" />
            <TextBlock Margin="10" Grid.Column="0" Grid.Row="2" Text="Password" Style="{StaticResource ResourceKey=SubheaderTextStyle}" />
            <PasswordBox Margin="10" Grid.Column="1" Grid.Row="2" Name="InputPassword" />
            <StackPanel  Margin="10" Grid.Column="1" Grid.Row="3" HorizontalAlignment="Left" Orientation="Horizontal">
                <Button Name="Login"  x:Uid="LoginPopupLogin"  />
                <Button Name="Cancel" x:Uid="LoginPopupCancel" />
            </StackPanel>
        </Grid>
    </Popup>

Here I have added an event Loaded="LoginPopup_Loaded_1" to the xaml of the popup

Here's the event code in C#

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

Explanation :

HorizontalOffset gets the distance between the left side of the application window and the left side of the popup.

Similarly vertical offset gets the distance between the top of the window and top of the popup

SINCE we have to center align it so we have to subtract half the width and the height of the popup from the the width and the height of the application window ( center of the popup is half the distance of the popup from it's top and left boundary )

the code is written in Loaded="LoginPopup_Loaded_1" event because this event is called when the element is rendered in the application window and Grid is taken because it is the container Grid of all the child elements.

i hope m clear :)

Anobik
  • 4,841
  • 2
  • 17
  • 32
  • That was actually what I was looking for, but I did not think about Loaded ;) Maybe you can tell me the difference between x:Name and Name? I seems that I was to quick, because it tells that the height and Width of the Grid is NaN – The87Boy Dec 17 '12 at 10:35
  • How about the size of the Grid? – The87Boy Dec 17 '12 at 12:15
  • And is it possible to run Loaded, when the screen is rotated? – The87Boy Dec 17 '12 at 12:33
  • I did not get the second question can u be a little more clear Re: How about the size of the Grid? – The87Boy 45 mins ago – Anobik Dec 17 '12 at 13:02
  • The height and width of the Grid is set to NaN in the Loaded-method – The87Boy Dec 17 '12 at 13:06
  • For this please go through the link from stack overflow http://stackoverflow.com/questions/607827/what-is-the-difference-between-width-and-actualwidth-in-wpf – Anobik Dec 17 '12 at 13:18
  • Yes, but ActualWidth and ActualHeight is set to NaN :s – The87Boy Dec 17 '12 at 14:08
  • 1
    in the loaded event or the constructor ?? – Anobik Dec 17 '12 at 14:11
  • 1
    You need to call LoginPopup.UpdateLayout() before accessing ActualWidth and ActualHeight, otherwise those values will not be valid yet. Also consider doing this in the Opened event instead of the Loaded event - I was unable to get it to work in the Loaded event even after calling UpdateLayout(). – mkelly4ca Jan 15 '14 at 23:01
  • Worked for me with @mkelly4ca's tip to move it to the `Opened` event, but it doesn't seem to need `UpdateLayout` then. Even with `UpdateLayout` it didn't work in the `Loaded` event. – Stephen Hosking Aug 23 '17 at 02:17
1

Re : And is it possible to run Loaded, when the screen is rotated? – The87Boy 24 mins ago

Answer to this is yes you can execute the same set of code by creating a method and call that method on Window.Current.SizeChanged += Current_SizeChanged;

 void Current_SizeChanged(object sender, Windows.UI.Core.WindowSizeChangedEventArgs e)
    {
        //call custom method from loaded event as well as size changed event
    }
Anobik
  • 4,841
  • 2
  • 17
  • 32
0

about the x:name and name attribute u asked what I'll explain will be same as what written in the below link

x:name and name difference silverlight

and also go through this link for WPF

In WPF, what are the differences between the x:Name and Name attributes?

As per my general understanding the Name is a property of the Class (ex: Grid or TextBlock and many more) but classes which do not have a name attribute needs to be accessed some how (ex: StoryBoard etc) so for that purpose x:name is provided. During the initializecomponent method call the x:name's and name are mapped to the class using FindName(string) method for them to become accessible.

now what happens internally is a long story cut short

MainPage.xaml -> MainPage.g.i.cs -> MainPage.xaml.cs

Community
  • 1
  • 1
Anobik
  • 4,841
  • 2
  • 17
  • 32