使用DrawingContext相对于中心绘制

时间:2012-10-23 03:44:43

标签: c# .net wpf drawingcontext

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

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

但是,对于另一个问题,没有这样的运气。有关如何集中我的起源的任何想法吗?

3 个答案:

答案 0 :(得分:1)

您可以使用在y方向上按-1缩放的MatrixTransform而不是ScaleTransform,并将坐标原点转换为控件的中心。但是,只要控件的大小发生变化,就必须更新此转换。因此,您将覆盖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();

分配给每个新Visual的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的Border子类”来管理你的视觉效果。典型的方法是将一个父ContainerVisual作为可视树的根。然后,变换将仅应用于此根视觉。

答案 1 :(得分:0)

您是否尝试过TranslateTransform

答案 2 :(得分: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;

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

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

当我添加一个新元素(顺便说一句Node)时,我只需要将其转换为WorldTransform的反转。

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