Wie kann ich einen Weg, hinzufügen, die zur Laufzeit in der XAML Resource, mehrere Male zu einer WPF-Form definiert wurde?
-
21-09-2019 - |
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?
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.