2009-09-04 14 views
11

我有一個定義的路徑在XAML:如何在運行時將已在XAML ResourceDictionary中定義的路徑多次添加到WPF表單中?

<UserControl.Resources> 
    <ResourceDictionary> 
     <Path x:Key="N44" Width="20" Height="80" Stretch="Fill" Fill="#FF000000" Data="M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z "/> 
    </ResourceDictionary> 
</UserControl.Resources> 

我想將它添加到WPF網格&做一次這樣的工作:

System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path(); 
aPath = (System.Windows.Shapes.Path)this.Resources["N44"]; 
LayoutRoot.Children.Add(aPath); 

但是,如果我上的按鈕添加以下代碼單擊事件,然後單擊該按鈕兩次,引發錯誤說明

「指定的Visual已經是另一個Visual或Roo的子項 t的 CompositionTarget。「

然後我試圖創建資源的兩個實例,但我一直收到相同的錯誤。下面是我本次測試使用的代碼:

private void cmbTest_Click(object sender, System.Windows.RoutedEventArgs e) 
    { 
    System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path(); 
    aPath = (System.Windows.Shapes.Path)this.Resources["N44"]; 

    if (LayoutRoot.Children.Contains(aPath) == true){ 
    System.Windows.Shapes.Path bPath = (System.Windows.Shapes.Path)this.Resources["N44"]; 
    LayoutRoot.Children.Add(bPath); 
    }else{ 
    aPath.Name = "a"; 
    aPath.Tag = "a"; 
    LayoutRoot.Children.Add(aPath); 
    } 
    } 

這樣,我怎麼能在運行時添加一個XAML路徑,它已在ResourceDictionary中被定義,多次到WPF的形​​式?

+0

你知道如何在XAML代碼中引用'N44'的數據嗎? – 2015-04-20 05:01:50

+0

這個問題是> 5歲。也許你應該問一個新問題。 – 2015-04-20 08:29:46

回答

12

因爲我已經發現,我已經錯過了documentation from MSDN的重要組成部分:

共享的類型和類型的UIElement:

資源字典是一種技術,用於 定義共享類型和值這些類型在XAML中。並非所有類型或 值都適用於ResourceDictionary的 。有關 關於哪些類型爲 的信息可以在Silverlight中共享,請參閱資源字典 。

特別是,所有的UIElement派生 類型是不共享的,除非他們 來自模板和 在一個特定的控制 實例的模板應用。排除模板案例, 一個UIElement預計只存在於一個對象樹中的一個地方 一旦 實例化,並且具有可共享的UIElement 可能會違反 這一原則。

我會總結爲,這不是它的作品,因爲它不是每次都創建一個新的實例我執行該代碼的方式 - 它只是創建對象的引用 - 這就是爲什麼它的工作一次,但不是多次。 因此,在閱讀更多內容後,我想出瞭解決我的問題的三種潛在方法。

1)使用技術創建到新對象的深層複製。

System.Windows.Shapes.Path newPath = (System.Windows.Shapes.Path)System.Windows.Markup.XamlReader.Parse("<Path xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation' Width='20' Height='80' Stretch='Fill' Fill='#FF000000' Data='M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z ' HorizontalAlignment='Left' VerticalAlignment='Top' Margin='140,60,0,0'/>"); 
LayoutRoot.Children.Add(newPath); 

3)只存儲:Deep cloning objects

2)商店的XAML應用程序中的字符串,然後使用XAML讀者創建路徑的情況下 - 從其他StackOverflow的問題示例資源字典中的路徑數據。在代碼中創建Path的新實例,將Path數據應用於新Path,然後手動添加我感興趣的其他屬性。

的XAML - 路徑數據存儲爲StreamGeometry:

<UserControl.Resources> 
    <ResourceDictionary> 
     <StreamGeometry x:Key="N44">M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z</StreamGeometry> 
    </ResourceDictionary> 
</UserControl.Resources> 

的C#代碼,然後創建一個實例,並應用其他值:

System.Windows.Shapes.Path bPath = new System.Windows.Shapes.Path(); 
bPath.Data = (System.Windows.Media.Geometry)this.FindResource("N44"); 

bPath.Width = 20; 
bPath.Height = 80; 

bPath.VerticalAlignment = System.Windows.VerticalAlignment.Top; 
bPath.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; 

left = left + 40; 

System.Windows.Thickness thickness = new System.Windows.Thickness(left,100,0,0); 
bPath.Margin = thickness; 

bPath.Fill = System.Windows.Media.Brushes.Black; 
LayoutRoot.Children.Add(bPath); 
+2

將Path.Data存儲爲資源中的StreamGeometry非常棒! – 2009-11-30 16:46:01

3

只需爲Path創建樣式,然後應用它。

+0

這是最好的清潔建議,因爲您將記住這個解決方案,用於跨平臺xaml中的類似場景。 – Quincy 2012-08-29 15:14:13

13

還有一個更簡單的,內置在這樣做的方式。 在資源上設置x:Shared =「False」。這將允許它被重用。然後根據需要多次使用它。

<UserControl.Resources> 
    <ResourceDictionary> 
     <Path x:Shared="False" x:Key="N44" Width="20" Height="80" Stretch="Fill" Fill="#FF000000" Data="..."/> 
    </ResourceDictionary> 
</UserControl.Resources> 
相關問題