2013-12-10 95 views
1

我的軟件創建了相當複雜的石器,將在畫布上繪製。由於這是多次顯示(預覽窗口,更大的視圖,...)我想緩存繪製的畫布。 我的第一個嘗試是爲什麼我不能將畫布對象分配給現有的畫布?

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; 
} 

但是,這並不表明任何東西。我可以,但是替換

MyCanvas.Children.Add(NewCanvas); 

最後一行現在我可以看到我的畫布,但如果我嘗試打開另一個窗口,顯示同樣的帆布

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

我得到一個System.ArgumentException:

「必須斷開當前父指定的子之前 視覺附加到新的父視覺。」

我研究了克隆canvas對象,但canvas對象不可序列化,並且XamlWriter需要在自定義編寫的UIElements類中使用特殊的構造函數,但我不知道它究竟需要什麼。

回答

0

讓我們先來看看你的錯誤,所以你得到一個更好的理解的代碼做什麼:

MyCanvas = NewCanvas; 

你想要什麼,因爲你只需更換參考這不會做。 MyCanvas是您實例中的一個變量,它首先指向一個Canvas實例(表單中顯示的空實例)。當您執行上述語句時,MyCanvas變量會被修改爲引用另一個Canvas實例 - 一個可能包含一些圖形元素的實例,但不會將其添加到您的窗口中。您的窗口繼續僅包含原始的空Canvas實例。

System.ArgumentException恰恰是因爲它所說的。您無法一次向多位父母添加視覺元素。


清潔器的解決辦法是不重複的完整Canvas,但有一種方法(或具有方法的對象),其採用一個Canvas作爲參數,然後創建並添加所有元素的Petri網包括到Canvas。在一個非常簡單的形式是這樣的:

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情況下,這種方法。

請注意,您也可以使用Petrinet類存儲描述您的Petri網數據 - 你可以使類序列化,所以你能堅持這些數據,因爲它是你自己的類:-)

0

你不能做你想做的。正如你的Exception告訴你的,在WPF中,每個UI元素只能在視覺樹中託管一次。基本上,這意味着如果UI元素正在UI中顯示,那麼您不能將該UI元素添加到UI中的另一個容器中。您可以從當前位置移除UI元素,然後將其添加到UI中的其他容器,但這不是您想要的。

要說清楚,我只是談論UI元素,而不是數據元素。一個數據元素可以在用戶界面中多次表示,雖然它的呈現形式可能看起來完全相同,但實際上它們都是不同的UI元素。

0
*`I get an System.ArgumentException: 「Must disconnect specified child from current parent Visual before attaching to new parent Visual.」`* 

在Windows Presentation Foundation(WPF)中,一個元素可以具有不超過一個可視父和不超過一個邏輯父。這實際上非常重要,因爲它確保了視覺和邏輯樹形成良好。

But that does not show anything at all. I can, however replace the last line with 這種正常的你正在創建一個新的對象,你應該爲了讓WPF做一切必要的計算 例如,你可以做這樣的事情

 this.yourGrid.Children.Add(NewCanvas); 
它添加到您的邏輯樹

I looked into cloning the canvas-object, but the canvas-object is not serializable

你不能序列化你的控制,你正在做的,你可以使用這樣的

 string saved = XamlWriter.Save(canvas1); 
     StringReader sReader = new StringReader(saved); 
     XmlReader xReader = XmlReader.Create(sReader); 
     Canvas newCanvas = (Canvas)XamlReader.Load(xReader); 
     yourGrid.Children.Add(newCanvas);