WPF Textblock translation based on reference point

北战南征 提交于 2019-11-29 16:02:48

Maybe you need this

void MoveToPoint(UIElement sender, Point point)
{
    Canvas.SetLeft(sender, point.X - sender.RenderTransformOrigin.X * sender.ActualWidth);
    Canvas.SetTop(sender, point.Y - sender.RenderTransformOrigin.Y * sender.ActualHeight);
}

to Xaml (patern MVVM): you need write converter and for properties Canvas.Left and Canvas.Top use Binding. It's more code than previously.

Example Converter (example 6) http://www.codeproject.com/Articles/29054/WPF-Data-Binding-Part

In converter need send 2 parameters sender.RenderTransformOrigin.X and ActualWidth.

Watch Converter with some params (in russian) - http://habrahabr.ru/post/141107/

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!