2009-09-04 9 views
11

Tengo un camino definido en XAML:¿Cómo puedo agregar una Vía de acceso, que se ha definido en XAML ResourceDictionary, varias veces a un formulario WPF en tiempo de ejecución?

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

quiero agregarlo a una WPF Gird & hacerlo una vez como esto funciona:

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

Sin embargo si añado este código en un botón haga clic en evento y luego haga clic en el botón dos veces, se produce un error que indica

"especificado visual ya es un hijo de otro visual o la Roo t de CompositionTarget ".

Intenté crear dos instancias del recurso pero he seguido recibiendo el mismo error. A continuación se muestra el código que he utilizado para esta prueba:

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

Como tal, ¿cómo puedo añadir una ruta de XAML, que ha sido definida en el ResourceDictionary, varias veces a una forma de WPF en tiempo de ejecución?

+0

¿Sabes cómo hacer referencia a los datos de 'N44' en el código xaml? –

+0

Esta pregunta es> 5 años de edad. Tal vez deberías hacer una nueva pregunta. –

Respuesta

12

desde entonces he descubierto que me había perdido una parte importante de los documentation from MSDN:

Tipos compartibles y tipos de UIElement:

Un diccionario de recursos es una técnica para la definición de tipos y valores de compartibles estos tipos en XAML. No todos los tipos o valores de son adecuados para el uso de un ResourceDictionary. Para obtener más información sobre sobre qué tipos son considerados compartibles en Silverlight, , vea los diccionarios de recursos.

En particular, todos UIElement deriva tipos no son compartible a menos que provienen de plantillas y aplicación de una plantilla en una instancia específica de control . Excluyendo el caso de la plantilla, , se espera que un UIElement solo exista en un solo lugar en un árbol de objetos una vez instanciado, y que tener un UIElement sea compartible podría violar el principio .

¿Qué voy a resumir como, esa no es la forma en que funciona porque no es la creación de una nueva instancia cada vez que ejecutar ese código - que sólo está creando una referencia al objeto - que es por qué funciona una vez, pero no muchas veces Así que después de leer un poco más, he encontrado tres formas posibles de resolver mi problema.

1) Utilice una técnica para crear una copia profunda de un objeto nuevo.Ejemplo de otra pregunta StackOverflow - Deep cloning objects

2) tienda el XAML en cadenas dentro de la aplicación y luego utilizar el lector XAML para crear instancias de los caminos:

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) Sólo almacenar el Datos de ruta en el Diccionario de recursos. Cree una nueva instancia de una ruta en el código, aplique los datos de ruta a la nueva ruta y luego agregue las otras propiedades que me interesan de forma manual.

El XAML - los datos de trayectoria se almacena como un 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> 

El código C# a continuación, crear una instancia y aplicar los demás valores:

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

Almacenar el Path.Data como un StreamGeometry en un recurso es brillante! –

3

Simplemente cree el estilo de la ruta y aplíquela.

+0

este es el mejor consejo para usar, ya que recordará esta solución para escenarios similares en Xaml multiplataforma. – Quincy

13

hay un más fácil, incorporado en forma de hacer esto. Establecer x: Shared = "False" en el recurso. Esto permitirá que sea reutilizado. Luego, úselo tantas veces como desee.

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