【问题标题】:Convert any old WPF Geometry to PathFigureCollection?将任何旧的 WPF 几何转换为 PathFigureCollection?
【发布时间】:2019-04-17 04:13:32
【问题描述】:

我有一系列与形状相关的视图模型类。您典型的传统层次结构:基本 ShapeVm 类,然后是 LineVm、CircleVm 等。每个都公开适当类型的 Geometry 属性。

public abstract class ShapeVm
{
    public abstract Geometry Geometry { get; }
}
public class LineVm : ShapeVm
{
    public override Geometry Geometry => new LineGeometry(P1, P2);
    public Point  P1 { get; set; }
    public Point  P2 { get; set; }
}

到目前为止,我已经使用相同的类型 Path 在 XAML 中公开了这些,而不管形状类型如何。

<Path Fill="Yellow" StrokeThickness="3" Data={Binding Geometry}"/>

但现在我希望能够对 XAML 中的每个 PathGeometry 应用变换。这给我带来了“让我的代码闻起来”性质的问题:

我的方法是在 XAML 中手动构造我的 Path 对象的 PathGeometry 并设置它的 Transform 属性。但我无法弄清楚如何干净地将所有各种几何类型(LineGeometry、EllipseGeometry 等)轻松转换为 PathGeometry。我需要为 PathGeometry 提供一个“Figures”属性。

<Path Fill="Yellow" Stroke="Blue" StrokeThickness="3">
    <Path.Data>
        <PathGeometry Figures="???" **** WHAT DO I USE HERE??? ***
                      Transform="{Binding MyViewGeoTransform}"/>
    </Path.Data>
</Path>

PathGeometry.Figures 属性属于 PathFigureCollection 类型。是否有内置转换器可以将任何旧的 WPF 几何转换为 PathFigureCollection? System.Windows.Media.GeometryConverter 似乎无法解决问题。

是否有一些我想念的明显简单的方法来做到这一点?我应该只写转换器吗?

(我意识到我可以为每种形状类型编写一个不同的数据模板,如果它最干净,我会这样做,但在 XAML 中仅使用一个 Path 对象符合我的简单感)

【问题讨论】:

  • Pathgeometry 有一个 addgeometry 方法。

标签: wpf


【解决方案1】:

将 Transform 应用于 Path 的最简单方法可能是设置其 RenderTransform 属性:

<Path Fill="Yellow" StrokeThickness="3"
      Data="{Binding Geometry}"
      RenderTransformOrigin="0.5,0.5"
      RenderTransform="{Binding MyViewGeoTransform}"/>

如果出于任何原因不希望这样做,您可以将 MultiBinding 与创建转换后的 GeometryGroup 的转换器一起使用:

<Path Fill="Yellow" StrokeThickness="3">
    <Path.Data>
        <MultiBinding Converter="{StaticResource TransformedGeometryConverter}">
            <Binding Path="Geometry"/>
            <Binding Path="MyViewGeoTransform"/>
        </MultiBinding>
    </Path.Data>
</Path>

转换器:

public class TransformedGeometryConverter : IMultiValueConverter
{
    public object Convert(
        object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var geometry = new GeometryGroup { Transform = (Transform)values[1] };
        geometry.Children.Add((Geometry)values[0]);
        return geometry;
    }

    public object[] ConvertBack(
        object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

【讨论】:

  • 谢谢,当你的答案进来时,我实际上正在尝试 TransformGeometry 方法。我同意,这对我来说似乎是最干净的。我无法使用 RenderTransform 方法,因为无论视图如何转换(特别是缩放),我都试图保持路径线的粗细相同。我只需要转换几何体。
  • 我应该说我使用的不是多转换器,而是一个简单的 IValueConverter。我要求用户将转换作为 ConverterParameter 传递。我想知道这与 IMultiValueConverter 方法相比是否有任何缺点。
  • 你不能绑定ConverterParameter,但是你的问题中有{Binding MyViewGeoTransform}
  • 道歉。我说错了。我没有“绑定” ConverterParameter。但我 am 让 ConverterParameter 使用 StaticResource 扩展来引用我的资源中的 Transform,它本身绑定到所需的属性。这种方法似乎有效,并且省去了我必须使用/编写 MultiConverter 和所有这些冗长的麻烦
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-18
  • 1970-01-01
  • 1970-01-01
  • 2020-10-01
  • 2020-07-11
  • 2011-10-04
  • 1970-01-01
相关资源
最近更新 更多