Wie kann ich einen Weg, hinzufügen, die zur Laufzeit in der XAML Resource, mehrere Male zu einer WPF-Form definiert wurde?

StackOverflow https://stackoverflow.com/questions/1377658

Frage

Ich habe einen definierten Weg in XAML:

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

Ich mag es zu einer WPF Gird hinzuzufügen und es einmal funktioniert wie folgt tun:

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

Allerdings, wenn ich diesen Code auf einem Ereignis Schaltfläche Klick hinzufügen und dann die Taste zweimal klicken, wird ein Fehler ausgelöst wird, die besagt,

  

"Angegebene Visuelle ist bereits ein Kind   einer anderen Sicht oder die Wurzel eines   CompositionTarget. "

Ich versuche dann zwei Instanzen der Ressource zu erstellen, aber ich habe weiterhin den gleichen Fehler erhalten. Unten ist der Code, dass ich für diesen Test verwendet:

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

Als solche, wie kann ich einen XAML-Pfad hinzufügen, die in der Resource, mehrfach zu einer WPF Form zur Laufzeit festgelegt wurden?

War es hilfreich?

Lösung 2

Ich habe da festgestellt, dass ich einen wichtigen Teil der Dokumentation von MSDN :

  

Gemeinsam nutzbare Typen und UIElement Arten:

     

Ein Ressource-Wörterbuch ist eine Technik für   definieren gemeinsam nutzbare Typen und Werten von   diese Arten in XAML. Nicht alle Typen oder   Werte sind für die Verwendung von einem geeigneten   Resource. Für mehr   Informationen darüber, welche Arten sind   als gemeinsam nutzbare in Silverlight,   siehe Ressourcen-Wörterbücher.

     

Insbesondere sind alle UIElement abgeleitet   Typen sind, wenn sie nicht gemeinsam nutzbare   kommt aus Vorlagen und Anwendung   eine Vorlage zu einem bestimmten Steuer   Beispiel. Ohne die Vorlage Fall,   ein UIElement ist nur exist erwartet   an einem Ort in einem Objektbaum einmal   instanziiert, und ein mit UIElement   sein gemeinsam nutzbare würde möglicherweise verletzen   dieses Prinzip.

Was ich so zusammenfassen werde, die nicht die Art und Weise ist es funktioniert, weil es ist nicht eine neue Instanz erstellen jedes Mal, wenn ich diesen Code ausführen - es ist nur eine Referenz auf das Objekt zu erzeugen - das ist, warum es funktioniert einmal aber nicht mehrfach. So nach einem bisschen mehr zu lesen Ich habe kommen mit 3 möglichen Wegen für eine Auflösung zu meinem Problem.

1) verwendet eine Technik, um eine tiefe Kopie auf ein neues Objekt zu erstellen. Beispiel aus anderer Stackoverflow Frage - Tief Klonen Objekte

2) Speichern Sie die XAML in Strings innerhalb der Anwendung und dann die XAML-Reader verwenden Instanzen der Pfade zu erstellen:

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) Nur speichern Sie die Pfadangaben in der Ressourcen-Wörterbuch. Erstellen Sie eine neue Instanz eines Pfades im Code, gilt die Pfaddaten an den neuen Pfad und fügen Sie dann die anderen Eigenschaften Ich bin an manuell.

Die XAML - Der Weg Daten als StreamGeometry gespeichert ist:

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

Der C # -Code dann eine Instanz erstellen und anwenden, die anderen Werte:

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

Andere Tipps

Es gibt eine einfachere, integrierte Möglichkeit, dies zu tun. Set x: Geteilt = "False" auf der Ressource. Dies ermöglicht es wiederverwendet werden. Benutzen Sie diese dann so oft wie Sie wollen.

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

Erstellen Sie einfach Stil für Path, und wenden Sie es.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top