Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.0k views
in Technique[技术] by (71.8m points)

wpf controls - WPF Textblock translation based on reference point

Please check the attached image. I made the textblock origin to it's center by RenderTransformOrigin="0.5,0.5". Now I would like to move the textblock based on the reference point. May be (0,0 ) or (10,10) or ...... These are absolute points. For example, in case of (0,0) the textblock should move to absolute (0,0) based on its reference point. I know how to move relatively by TranslateTransform, but this case I need absolute transform.

enter image description here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to WuJiGu Developer Q&A Community for programmer and developer-Open, Learning and Share
...