How to Reposition a Silverlight Child Window?



Sometime we need to reset the position of the Silverlight Child Window at the center of the screen. This generally require when you have a static instance of the ChildWindow and you want to use the same instance to show various messages in the screen. When you loads the ChildWindow for the first time, by default it loads at the screen center. But think when your user reposition that ChildWindow to a different location in the screen, closes and reopens it, what will happen?

 

What will you see is, the ChildWindow opens at the same location where the user closes it last time. So, how can we reset it to the center of the screen? This small tip will help you to achieve the functionality. Read it to know more details. Code is available for use.

 

The Silverlight ChildWindow internally implements it’s Template with a Grid named “ContentRoot”. If you edit your ChildWindow Template, you will see the following code:

 
<Grid x:Name="ContentRoot" 
      HorizontalAlignment="{TemplateBinding HorizontalAlignment}" 
      VerticalAlignment="{TemplateBinding VerticalAlignment}" 
      Height="{TemplateBinding Height}" Width="{TemplateBinding Width}"
      RenderTransformOrigin="0.5,0.5">
    <Grid.RenderTransform>
        <TransformGroup>
            <ScaleTransform/>
            <SkewTransform/>
            <RotateTransform/>
            <TranslateTransform/>
        </TransformGroup>
    </Grid.RenderTransform>
.
.
.
</Grid>

 

You will see, it has a Grid named “ContentRoot”, which also has RenderTransform implemented in it. The TransformGroup of the Grid.RenderTransform contains various transformation of the Grid panel like ScaleTransform, SkewTransform, RotateTransform and TranslateTransform.

 

Here the TranslateTransform is use to position the ChildWindow. If you can set the X and Y coordinates of the TranslateTransform of the ChildWindow, you are done.

 

In this post, I will show you how to achieve that. To do this, we will create a Extension class for the ChildWindow and will implement the method to center it in the screen.

 

Let’s have a look into the implemented class here:

 

 
/// <summary>
/// Extension class to do some extra operation with Silverlight ChildWindow.
/// </summary>
public static class ChildWindowExtensions
{
    /// <summary>
    /// Centers the Silverlight ChildWindow in screen.
    /// </summary>
    /// <param name="childWindow">The child window.</param>
    public static void CenterInScreen(this ChildWindow childWindow)
    {
        var root = VisualTreeHelper.GetChild(childWindow, 0) as FrameworkElement;
        if (root == null) { return; }
 
        var contentRoot = root.FindName("ContentRoot") as FrameworkElement;
        if (contentRoot == null) { return; }
 
        var group = contentRoot.RenderTransform as TransformGroup;
        if (group == null) { return; }
 
        TranslateTransform translateTransform = null;
        foreach (var transform in group.Children.OfType<TranslateTransform>())
        {
            translateTransform = transform;
        }
 
        if (translateTransform == null) { return; }
 
        // reset transform
        translateTransform.X = 0.0;
        translateTransform.Y = 0.0;
    }
}

 

We created a static class having a static method “CenterInScreen()” which takes the instance of the ChildWindow as the parameter. From the instance of the ChildWindow, we will get the root which is nothing but a Grid. This Grid consists of another Grid named “ContentRoot”. Once you get the ContentRoot from the ChildWindow template, we can iterate through the TransformGroup to find the TranslateTransform. It is by default present in ChildWindow. Once you get the Translate Transform, change it’s X and Y coordinate values to ‘0’ (zero).

 

That’s all about it. If you want to position it somewhere else, set them there instead of ‘0’. Remember that, before doing this operation i.e. before calling the CenterInScreen() your Child Window needs to be added in the layout. If you didn’t add the ChildWindow to the layout before calling the method, you will see the “ArgumentOutOfRangeException”:

 

image

 

The extension method will help you to call the CenterInScreen() directly from the ChildWindow instance. Hope this information will help you when you work with the same.

9 comments

  1. I tried your code and I had to modify it for it to work. I had to move the lines that reset x and y to 0 inside the foreach. Thanks for sharing!

    ReplyDelete
  2. Hi Aztec,

    Thanks for trying it out. Actually, you can put it anywhere but it is better to put them outside the foreach loop because your RenderTransform group can have only one translate transform or no TranslateTransform. If it has Translate Transform then only it will reset the values else it will just return. In your case, it may through exception if translatetransform is null.

    ReplyDelete
  3. Hey Kunal, I actually used your code for the FloatableWindow control and I realized resetting the very last Translate Transform object in the collection was not enough so I decided to reset every one on them inside the foreach loop. So far so good :)

    Thank you!

    ReplyDelete
  4. Hello Kunai,

    Can you tell me when I can use it if I have ListBox in ChildWindow which is filled after ChildWindow are opened ?

    Right now I have:
    - call ChildWindow,
    - ChildWindow show on center of screen,
    - ViewModel load data from WCF,
    - ViewModel notify ListBox that data for ListBox.ItemsSource are ready to get,
    - Items are generated in my ListBox,

    and unfortunatelly my ChildWindow rezises in wrong way because, his position is not in center of screen :/

    I tried call your function after bind data to ListBox but without effect.

    ReplyDelete
  5. Hello Lukas,

    If your Child Window resizes after populating the ListBox, you may call it in the SizeChanged event otherwise find out the proper event where you can use this method call.

    ReplyDelete
  6. Hey, thanks. I was dealing with an issue similar to this today with Silverlight - your same extension code was quite helpful.

    ReplyDelete
  7. Hi Kunal,

    When I am trying to used the above class. I am getting an error like
    "using System.Windows.Media.TransformCollection does not contain a definition for 'ofType' and no extension method 'ofType ' accepting a first argument of type 'System.Windows.Media.TransformCollection ' could be found (are you missing a using directive or an assembly reference)".

    Can u help me out from this problem.


    Regards
    Surya.S

    ReplyDelete
  8. you have to use system.linq to get the "ofType" extension method

    ReplyDelete
  9. Hi Kunal,

    I want to change the size of child window when the browser restored. I am able to change the size of child window but the window is not always positioned at the centre of the screen. I tried your code but I am not able to reposition it the first time I restore the browser.

    Regards,
    Mustafa.

    ReplyDelete


 
© 2008-2014 Kunal-Chowdhury.com | Designed by Kunal Chowdhury
Back to top