According to MS knowledge base, it is possible to specify a RenderTransformOrigin to each transform operation to be applied to an object. See this article
It says: “When you apply a Transform to the RenderTransform property of a UIElement, you can use the RenderTransformOrigin property to specify an origin for every Transform that you apply to the element”.
With this information I expected to be able to use the TransformGroup with multiple rotations, each of them around their own center point, one of them being the center of the element which is given by the relative coordinate (0.5, 0.5).
I haven’t really found any way or any sample on how to define RenderTransformOrigin for a transform, as said is possible (though not demonstrated) in the article, so I gave a try to see if setting RenderTransformOrigin for the object takes it into consideration when not specifying CenterX and CenterY. That is, I was assuming that for any RotateTransform without explicit center x/y, it would use the relative coordinate in RenderTransformOrigin.
My assumption, however, is wrong. See this simple test:
MainWindow.xaml:
<Window x:Class="RenderTransformOrigin.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RenderTransformOrigin"
mc:Ignorable="d"
Title="MainWindow" Height="540" Width="500">
<StackPanel>
<Canvas x:Name="cv" Height="500" Width="500"/>
</StackPanel>
</Window>
MainWindow.xaml.cs:
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace RenderTransformOrigin
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TextBlock tblock = new TextBlock() { Text = "A", FontSize = 30, FontWeight = FontWeights.Bold };
tblock.Measure(new Size());
tblock.Arrange(new Rect());
cv.Measure(new Size());
cv.Arrange(new Rect());
tblock.RenderTransformOrigin = new Point(0.5, 0.5);
TransformGroup tgroup = new TransformGroup();
tgroup.Children.Add(new TranslateTransform() { X = (cv.ActualWidth - tblock.ActualWidth) / 2, Y = (cv.ActualHeight - tblock.ActualHeight) / 2 - 100 });
tgroup.Children.Add(new RotateTransform() { Angle = 90, CenterX = (cv.ActualWidth - tblock.ActualWidth) / 2 , CenterY = (cv.ActualHeight - tblock.ActualHeight) / 2 });
//tgroup.Children.Add(new RotateTransform() { Angle = -90 });
tblock.RenderTransform = tgroup;
cv.Children.Add(tblock);
}
}
}
The program places a TextBlock in a Canvas slightly off center in Y and centered in X. First it rotates the text by 90 degrees, and then the idea is to rotate the text around its center to make it face the reader again.
See that I assigned RenderTransformOrigin before any transform. With the second rotation commented out, it doesn’t affect the first rotation with its explicit center x/y. If you uncomment the line, the text is certainly rotated around the canvas origin (0, 0) because it goes off screen. Adding { CenterX = 0.5, CenterY = 0.5 } makes no difference, though I would think it is redundant after setting RenderTransformOrigin.
So my question is, how can I use the relative coordinates for a transform given the fact that the transform group has other transforms with different centers that have to be preserved?
You can see similar questions being asked in S.O. before, without successful answers:
C# WPF How to change RenderTransformOrigin but keep location?
Multiple RotateTransforms with different origins