the textblock should move to absolute (0,0)
I assume that by "absolute" you mean "relative to the MainWindow". I don't think there's a built-in render transform to coordinates relative to another element. But, you could always use a binding for X
and Y
-- I guess it would have to be a MultiBinding to allow you to convert a) the MainWindow, b) the TextBlock, to the "relative" offset corresponding to an absolute coordinate in the MainWindow.
The XAML should be something like this (X coordinate only here, for example). You could specify the target "absolute" point in the ConverterParameter
:
<TextBlock Text="TextBlock" RenderTransformOrigin="0.5,0.5">
<TextBlock.RenderTransform>
<TranslateTransform>
<TranslateTransform.X>
<MultiBinding>
<MultiBinding.ConverterParameter>
<Point X="10" Y="10" />
</MultiBinding.ConverterParameter>
<MultiBinding.Converter>
<converters:TranslateConverter />
</MultiBinding.Converter>
<Binding RelativeSource="{RelativeSource AncestorType=Window}" />
<Binding RelativeSource="{RelativeSource AncestorType=TextBlock}" />
</MultiBinding>
</TranslateTransform.X>
</TranslateTransform>
</TextBlock.RenderTransform>
</TextBlock>
The "TranslateConverter" is where you convert your reference (the window) and target (the TextBlock) to a relative offset. Use TransformToVisual
to convert the coordinates of the TextBlock to those of the Window.
public class TranslateConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var window = values[0] as Window;
var textblock = values[1] as TextBlock;
Point absolutePoint = (parameter as Point?) ?? new Point(0, 0);
// convert the target point from the Window's coordinates to the TextBlock's coordinates
var generalTransform = window.TransformToVisual(textblock);
Point offset = generalTransform.Transform(absolutePoint);
// get the position of the RenderTransform origin in the TextBlock's coordinates
Point relativePoint = textblock.RenderTransformOrigin;
double reference = relativePoint.X * textblock.ActualWidth;
// the relative offset of the 2 values above will move the TextBlock's origin to an "absolute" position
return offset.X - reference;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The above does the transform for X only, but you can extend it to do both X and Y by using a separate converter class for each coordinate.
One note about the above: the transformation will only run once, on load. If the TextBlock is moving around, and you need to perform the transformation continuously, then you might have to get creative. :)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…