six.strings.and.a.bit
six.strings.and.a.bit

Reputation: 527

How can I get the new position and size of a UIElement after performing a RenderTransform (Scale & Translate)?

I am performing scaling, translation and rotation on an image using RenderTransform. Transformations are not done using mouse events, rather, the user will click a button and then the image will scale/translate/rotate on a fixed value.

My problem is I want to determine the new position/size of the image each time a scaling, translation or rotation is performed. So I added Changed events on the code-behind. The question is how do you get the new position/size?

Please take a look at what I've done so far:

XAML:

<Border x:Name="mainImageBorderCtrl" ClipToBounds="True">
     <Grid x:Name="imageGridCtrl">
          <Grid.RenderTransform>
               <TranslateTransform Changed="TranslateTransform_Changed"/>
          </Grid.RenderTransform>
          <Image x:Name="mainImageCtrl" RenderTransformOrigin="0.5, 0.5" Source="{Binding Image}">
               <Image.RenderTransform>
                    <TransformGroup>
                         <ScaleTransform Changed="ScaleTransform_Changed"/>
                         <RotateTransform />
                    </TransformGroup>
               </Image.RenderTransform>
          </Image>
     </Grid>
</Border>

Please note that I separated TranslateTransform from ScaleTransform and RotateTransform so that the orientation won't be affected.

The following are the 2 changed events. In here, I expect to get the new position/size every time a scale or a translate has occurred. But the bounds values do not change.

Code-behind

private Rect bounds;

private void TranslateTransform_Changed(object sender, EventArgs e)
{
     bounds = imageGridCtrl.TransformToAncestor(mainImageBorderCtrl).TransformBounds(new Rect(imageGridCtrl.RenderSize));
}

private void ScaleTransform_Changed(object sender, EventArgs e)
{
     bounds = imageGridCtrl.TransformToAncestor(mainImageBorderCtrl).TransformBounds(new Rect(imageGridCtrl.RenderSize));
}

EDIT: My goal here is to restrict the translation(panning) of the Image inside the Border control, that's why I need to get the bounds of the Image after each transformation, whatever the transformation is, so that I can check whether the bounds of the Image exceeds the Border.

Upvotes: 3

Views: 2399

Answers (2)

Eli Arbel
Eli Arbel

Reputation: 22747

The transform change events fire too early. You should hook up to LayoutUpdated event of the image control. Then try:

mainImageCtrl.TransformToAncestor(mainImageBorderCtrl)
    .TransformBounds(new Rect(mainImageCtrl.RenderSize))

Upvotes: 1

Rohit Vats
Rohit Vats

Reputation: 81333

TranslateTransform is generating correct bounds. However, for ScaleTransform you are getting bounds on control imageGridCtrl but the transform is added as child of control mainImageCtrl.

So you should use mainImageCtrl in place of imageGridCtrl to get correct bounds:

bounds = mainImageCtrl.TransformToAncestor(mainImageBorderCtrl)
                      .TransformBounds(new Rect(mainImageCtrl.RenderSize));

Upvotes: 3

Related Questions