将控件位置绑定到另一个路径

本文关键字:另一个 路径 绑定 控件 位置 | 更新日期: 2023-09-27 18:00:52

我有一个Path,他的数据来自LineGeometry。我还有一个TextBlock,它是在创建路径时创建的。让TextBlock的位置跟随Path的位置的正确方法是什么?

将控件位置绑定到另一个路径

有很多方法

  • 在自定义面板中包含Path和TestBlock,并实现MeasureOverride和ArrangeOverride
  • 使用已存在的面板(Grid、StackPanel等(
  • 听Path对象的LayoutUpdated,然后使用TranslatePoint方法定位TextBlock

每种方式都有其缺点和优点,这取决于整个窗口的布局以及路径的布局变化的动态性。

最简单的解决方案可能是将Path和TextBlock放入一个公共容器中,该容器在TextBlock上执行必要的布局。这可能是一个网格:

<Canvas>
    <Grid>
        <Path ... />
        <TextBlock Text="Label" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    </Grid>
</Canvas>

您还可以通过将TextBlock的RenderTransform(或LayoutTransform(绑定到Path的Geometry来相对于Path的中心定位TextBlock,并使用绑定转换器进行实际计算。转换器将例如将Geometry转换为TranslateTransform。请注意,它甚至不要求几何图形是LineGeometry。它只是使用几何体的Bounds。但是,您可以根据几何体的实际类型进行任何专门的计算。

public class GeometryCenterConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var result = new TranslateTransform();
        var geometry = value as Geometry;
        if (geometry != null)
        {
            result.X = (geometry.Bounds.Left + geometry.Bounds.Right) / 2;
            result.Y = (geometry.Bounds.Top + geometry.Bounds.Bottom) / 2;
        }
        return result;
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

你可以这样写绑定:

<Path Name="path" ... />
<TextBlock Text="Label"
    RenderTransform="{Binding Path=Data, ElementName=path,
                      Converter={StaticResource GeometryCenterConverter}}"/>

请注意,上面的示例没有考虑TextBlock的任何对齐。如果需要居中或右下对齐,则可能需要更复杂的绑定(可能是MultiBinding(,或者可以将所有元素放在Canvas中,并在TextBlock上适当地设置Canvas.LeftCanvas.Top