具有多个底层视觉效果的自定义WPF画布

  • 本文关键字:自定义 WPF 画布 视觉 wpf
  • 更新时间 :
  • 英文 :


找到一篇有趣的文章,描述如何通过为Panel类的底层视觉效果公开方法AddRemove来创建自定义画布控件。通过这种方式,我可以创建一个通用的画布,它可以完全容纳任何在上面绘制的方式,GDI+,canvas,Drawings等。例如,第一层将是Bitmap,第二层Canvas,第三层DrawingVisual等。

为了简单起见,我想扩展现有的Canvas,这样我就可以通过默认Canvas控件提供原始行为,并且可以创建任意多的额外Visuals

这是我现在拥有的。

public class VisualCanvas : Canvas
{
protected IList<Visual> _visuals = null;
protected override int VisualChildrenCount => _visuals.Count;
protected override Visual GetVisualChild(int index) => _visuals.ElementAtOrDefault(index);
public VisualCanvas()
{
_visuals = new List<Visual>();
_visuals.Add(new DrawingVisual());
//(_visuals[0] as DrawingVisual).RenderOpen();
}
public void AddVisual(Visual visual)
{
_visuals.Add(visual);
base.AddVisualChild(visual);
base.AddLogicalChild(visual);
}
public void DeleteVisual(Visual visual)
{
_visuals.Remove(visual);
base.RemoveVisualChild(visual);
base.RemoveLogicalChild(visual);
}
}

不幸的是,我在构造函数中添加的DrawingVisual并没有使该控件的行为像原始的Canvas,因为我重写的两个方法似乎期望不同类型的Visual,而不是DrawingVisual

如何使此控件像原始Canvas一样工作?

在MSDN上发现了类似的问题。似乎仅仅覆盖两个方法来将所有子项保持在一个视觉列表中是不够的。默认画布集合InternalChildren也需要考虑在内。

这个实现似乎保留了默认的画布行为+新的视觉效果,但可能有不可预测的行为,因为两个类集合共享相同的索引。看起来用每个视觉类型的新属性来扩展这个类会更容易,而不是试图覆盖现有的属性。请随意发布更好的想法和实现。

public class VisualCanvas : Canvas
{
protected IList<Visual> _visuals = new List<Visual>();
protected override int VisualChildrenCount => _visuals.Count + InternalChildren.Count;
protected override Visual GetVisualChild(int index) => _visuals.ElementAtOrDefault(index) ?? InternalChildren[index - _visuals.Count];
public void AddVisual(Visual visual)
{
_visuals.Add(visual);
base.AddVisualChild(visual);
base.AddLogicalChild(visual);
}
public void DeleteVisual(Visual visual)
{
_visuals.Remove(visual);
base.RemoveVisualChild(visual);
base.RemoveLogicalChild(visual);
}
}

最新更新