【问题标题】:WPF Textblock translation based on reference point基于参考点的 WPF 文本块翻译
【发布时间】:2014-05-24 21:55:08
【问题描述】:

请检查所附图片。我通过 RenderTransformOrigin="0.5,0.5" 将文本块原点设置为它的中心。现在我想根据参考点移动文本块。可能是 (0,0 ) 或 (10,10) 或......这些是绝对点。例如,在 (0,0) 的情况下,文本块应根据其参考点移动到绝对 (0,0)。我知道如何通过 TranslateTransform 进行相对移动,但这种情况下我需要绝对变换。

【问题讨论】:

  • 您是否希望TextBlock 的位置在运行时移动(需要重新计算其渲染变换),或者它只是在 Window / TextBlock 首先移动时的一次移动加载?
  • @McGarnagle,实际上文本的集合是来自数据源的动态,我需要在窗口加载后动态定位文本(例如,简单的情况,如果用户输入文本和位置一个文本框,它应该根据输入显示在画布中)
  • 顺便说一句,为什么这个过程在 WPF 中如此复杂?我来自 winform 方面,现在开始关注 WPF :-)
  • 实际上,可能有一种更简单的方法可以到达您要去的地方,使用面板或其他东西(例如,给元素一个绝对位置,通常您应该使用 Canvas)。换句话说,正如他们所说,您可能提出了“XY 问题”。我的回答绝对看起来像是一个过于复杂的 hack。

标签: wpf wpf-controls textblock


【解决方案1】:

也许你需要这个

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);
}

到 Xaml(模式 MVVM): 您需要编写转换器,并且对于属性 Canvas.Left 和 Canvas.Top 使用绑定。代码比以前多了。

示例转换器(示例 6)http://www.codeproject.com/Articles/29054/WPF-Data-Binding-Part

在转换器中需要发送 2 个参数 sender.RenderTransformOrigin.X 和 ActualWidth。

观看带有一些参数的转换器(俄语)-http://habrahabr.ru/post/141107/

【讨论】:

  • @@m4a,这是一个很棒的解决方案,我会根据我的要求修改答案,但是您能否解释一下如何将此解决方案集成到 XAML,如果我想将所有元素移至某一点?
  • 太好了,实际上我正在遵循 MVVM 模式。我有谷歌翻译:P。非常感谢
  • @@m4a,例如,通常我可以在仅将控件放置到画布后了解 UIElement 的 ActualWidth。万一,如果我想将控件直接放置到某个点,该怎么做?
【解决方案2】:

文本块应该移动到绝对 (0,0)

我假设“绝对”是指“相对于 MainWindow”。我认为相对于另一个元素的坐标没有内置的渲染转换。但是,您始终可以为XY 使用绑定——我想它必须是一个MultiBinding 才能让您将a)MainWindow,b)TextBlock 转换为对应于的“相对”偏移量MainWindow 中的绝对坐标。

XAML 应该是这样的(例如,仅此处的 X 坐标)。您可以在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>

“TranslateConverter”是您将参考(窗口)和目标(TextBlock)转换为相对偏移的地方。使用TransformToVisual将TextBlock的坐标转换为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();
    }
}

以上仅对 X 进行转换,但您可以通过为每个坐标使用单独的转换器类将其扩展为同时执行 X 和 Y。


关于上述内容的一点说明:转换只会在加载时运行一次。如果 TextBlock 正在四处移动,并且您需要不断地执行转换,那么您可能需要发挥创造力。 :)

【讨论】:

  • 但我想知道,文本放置是一个重要的功能,它是如何正确放置在绝对点的,比如 Moveto (5,5)
  • @Robin 我没有关注您的评论...我以为您想将 TextBlock 中的相对点“拖动”到窗口中的绝对位置?
  • @@McGarnagle,不不,我只是想将文本块(假设中心点现在是参考)移动到画布中的某个位置。它可能是 (5,10) 或其他东西。当我说移动到 (5,10) 时,文本块应该移动到 (5,10),这意味着中心参考点在 (5,10)...
  • @Robin 对,这是我的理解。我相信上面的方法可以做到这一点(好吧,只针对X坐标,但它应该是正确的原则)。
  • @@McGarnagle,谢谢,我会尝试并将其标记为答案。顺便说一句,为什么这个过程在 WPF 中如此复杂?我来自 Winform,现在开始关注 WPF :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多