为什么我不能将画布对象分配给现有画布? [英] Why can't I assign a canvas-object to an existing canvas?

查看:36
本文介绍了为什么我不能将画布对象分配给现有画布?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的软件创建了将在画布上绘制的相当复杂的 petrinet.由于这被多次显示(预览窗口,更大的视图,......)我想缓存绘制的画布.我的第一次尝试是

My software creates rather complex petrinets that will be drawn on a canvas. Since this is shown multiple times (a preview window, a larger view, …) I would like to cache the drawn canvas. My first try was

XAML:

<Canvas Name="MyCanvas" />

背后的代码:

public MainWindow()
{
    InitializeComponent();

    Canvas NewCanvas = new Canvas();
    TextBlock txt1 = new TextBlock();
    txt1.Text = "Hello World!";
    Canvas.SetTop(txt1, 10);
    Canvas.SetLeft(txt1, 10);
    NewCanvas.Children.Add(txt1);

    MyCanvas = NewCanvas;
}

但这根本没有显示任何内容.但是我可以用

But that does not show anything at all. I can, however replace the last line with

MyCanvas.Children.Add(NewCanvas);

现在我可以看到我的画布,但是如果我尝试打开另一个显示相同画布的窗口

Now I can see my canvas, BUT if I try to open another window showing the same canvas

Window NewWindow = new Window();
NewWindow.Content = NewCanvas;
NewWindow.Show();

我收到一个 System.ArgumentException:

I get an System.ArgumentException:

之前必须断开指定的子级与当前父级 Visual附加到新的父视觉对象."

"Must disconnect specified child from current parent Visual before attaching to new parent Visual."

我研究了克隆画布对象,但画布对象不可序列化,并且 XamlWriter 在自定义编写的 UIElements 类中需要一个特殊的构造函数,但我不知道它到底需要什么.

I looked into cloning the canvas-object, but the canvas-object is not serializable, and XamlWriter needs a special contructor in the custom-written UIElements-classes, but I don't have a clue what exactly it needs.

推荐答案

让我们先看看您的错误,以便您更好地理解代码的作用:

Let's first look at your errors so you get a better understanding for what the code does:

MyCanvas = NewCanvas;

这不能满足您的要求,因为您只是替换了引用.MyCanvas 是您实例中的一个变量,它首先指向一个 Canvas 实例(表单中显示的空实例).当你执行上面的语句时,MyCanvas 变量被修改为引用另一个 Canvas 实例——一个 Canvas 实例,它可能包含一些图形元素,但是这绝不会添加到您的窗口中.您的窗口继续只包含原始的空 Canvas 实例.

This does not do what you want because you simply replace the reference. MyCanvas is a variable in your instance that at first points to a Canvas instance (the empty instance that is shown in your form). When you execute the above statement, the MyCanvas variable is modified to reference another Canvas instance - a Canvas instance that may contain some graphical elements, but that is at no point added to your window. Your window continues to just contain the original, empty Canvas instance.

System.ArgumentException 的发生正是因为它所说的.您不能一次向多个父项添加视觉元素.

The System.ArgumentException occurs exactly because of what it says. You cannot add a visual element to several parents at a time.

更简洁的解决方案不是复制完整的 Canvas,而是有一个方法(或带有方法的对象),它以 Canvas 作为参数,并且然后创建您的 petrinet 包含的所有元素并将其添加到 Canvas.以非常简化的形式如下:

The cleaner solution would be not to duplicate the complete Canvas, but to have a method (or an object with a method) that takes a Canvas as a parameter and then creates and adds all the elements your petrinet comprises of to the Canvas. In a very simplified form like this:

public class Petrinet
{
    public void OutputPetrinet(Canvas dest)
    {
        if (dest == null) {
            throw new ArgumentNullException("dest");
        }

        Ellipse e = new Ellipse() {
            Width = 50,
            Height = 60,
            Fill = Brushes.Blue
        };
        Canvas.SetLeft(e, 20);
        Canvas.SetTop(e, 30);
        dest.Children.Add(e);
    }
}

然后,您可以根据需要为任意数量的 Canvas 实例调用此方法.

You can then invoke this method for as many Canvas instances as you like.

请注意,您还可以使用该 Petrinet 类来存储描述您的 petrinet 的数据 - 并且您可以使该类可序列化,以便您可以保留该数据,如这是你自己的班级:-)

Note that you can also use that Petrinet class to store the data that describes your petrinets - and you can make that class serializable so you can persist that data, as it's your own class :-)

这篇关于为什么我不能将画布对象分配给现有画布?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆