WPF Textblock translation based on reference point

我是研究僧i 提交于 2019-12-03 18:12:16

问题


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.


回答1:


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/




回答2:


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



来源:https://stackoverflow.com/questions/23000804/wpf-textblock-translation-based-on-reference-point

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