0

我一直想知道如何在 WPF 中绘制DrawingContext相对于控件左上角以外的东西的东西。我的问题是我想通过连接各种点来绘制一些形状,并且这些点必须相对于主机控件的中心定位,Y 指向上方。

我的元素是使用自定义子类树呈现的DrawingVisual,根是Border包含VisualCollection. ScaleTransform我通过将 a 指定为RenderTransformthat来解决 Y 方向问题Border,基本上垂直翻转整个控件。

不过,其他问题就没有这样的运气了。关于如何将我的原点居中的任何想法?

4

3 回答 3

1

您可以使用 MatrixTransform 代替 ScaleTransform,它在 y 方向上按 -1 缩放并将坐标原点转换到控件的中心。但是,只要控件的大小发生变化,就必须更新此转换。因此,您将覆盖 OnRenderSizeChanged,如下所示(假设您设置了RenderTransform控件的属性):

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    base.OnRenderSizeChanged(sizeInfo);

    RenderTransform = new MatrixTransform(1d, 0d, 0d, -1d,
        sizeInfo.NewSize.Width / 2d, sizeInfo.NewSize.Height / 2d);
}

编辑:如果您不想转换整个控件,您还可以将 MatrixTransform 定义为类成员并将其应用于可视子集合中的每个 Visual。

private MatrixTransform transform = new MatrixTransform();

分配给每个新视觉对象的 Transform 属性:

ContainerVisual visual = ...
visual.Transform = transform;

在大小更改时,您只需更新 MatrixTransform:

protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
    base.OnRenderSizeChanged(sizeInfo);

    transform.Matrix = new Matrix(1d, 0d, 0d, -1d,
        sizeInfo.NewSize.Width / 2d, sizeInfo.NewSize.Height / 2d);
}

当然,您只需要将变换应​​用到“顶级”视觉效果。这些视觉的孩子将被他们父母的变换所改变。我不完全了解您如何通过“包含 VisualCollection 的边框子类”来管理您的视觉效果。典型的方法是让一个父 ContainerVisual 作为可视化树的根。然后将仅将变换应用于此根视觉对象。

于 2012-10-23T07:31:15.853 回答
0

你试过TranslateTransform吗?

于 2012-10-23T03:50:05.583 回答
0

好吧,我明白了。这就是我的做法。

首先,我定义了一个GroupTransform并分配给WorldTransform我的子类的一个属性Border

var trans = new TranslateTransform();
var conv = new HalfConverter(); // a custom converter that halves whatever you pass to it
BindingOperations.SetBinding(trans, TranslateTransform.XProperty, new Binding { Path = new PropertyPath(ActualWidthProperty), Source = this, Converter = conv });
BindingOperations.SetBinding(trans, TranslateTransform.YProperty, new Binding { Path = new PropertyPath(ActualHeightProperty), Source = this, Converter = conv });

WorldTransform = new TransformGroup();
WorldTransform.Children.Add(new ScaleTransform { ScaleY = -1.0 });
WorldTransform.Children.Add(trans);
VisualTransform = WorldTransform;

然后,当我创建 custom 的新实例时DrawingVisual,我将其Transform属性分配给我的WorldTransform.

// ZoneVisual is my DrawingVisual subclass
var vis = new ZoneVisual(zone) { Transform = WorldTransform };

当我添加一个新元素(Node顺便说一下,a)时,我只需要将其转换为 my 的倒数WorldTransform

瞧。这可能不是最好的方法,但它似乎工作得很好。我没有非常高的性能需求,所以它可能会完成这项工作。

于 2012-10-25T00:52:02.653 回答