Comment puis-je ajouter un chemin, qui a été défini dans le XAML ResourceDictionary, plusieurs fois à une forme WPF lors de l'exécution?

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

Question

J'ai un chemin défini en 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>

Je veux l'ajouter à un WPF Gird et le faire une fois comme cela fonctionne:

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

Cependant, si j'ajouter ce code sur un événement de clic de bouton, puis cliquez sur le bouton deux fois, une erreur est renvoyée indiquant

  

"spécifié visuel est déjà un enfant   d'un autre visuel ou la racine d'un   CompositionTarget. "

Je puis tenté de créer deux instances de la ressource, mais je continue à recevoir la même erreur. Voici le code que j'ai utilisé pour ce test:

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

En tant que tel, comment puis-je ajouter un chemin XAML, qui a été défini dans le ResourceDictionary, plusieurs fois à une forme WPF lors de l'exécution?

Était-ce utile?

La solution 2

Je l'ai trouvé depuis que je l'avais manqué une partie importante de la documentation de MSDN :

  

partageables Types et types UIElement:

     

Un dictionnaire de ressources est une technique pour   définir les types et les valeurs de partageables   ces types en XAML. Tous les types ou   Les valeurs sont appropriées pour une utilisation à partir d'un   ResourceDictionary. Pour plus   informations sur quels types sont   considéré partageable dans Silverlight,   voir ressources dictionnaires.

     

tous UIElement dérivé En particulier,   types ne sont pas partageables à moins qu'ils ne   proviennent de modèles et application de   un modèle sur un contrôle spécifique   exemple. Hors le cas du modèle,   un UIElement devrait exister que   en un seul endroit dans un arbre objet une fois   instanciée, et ayant une UIElement   être partageable serait potentiellement violer   ce principe.

Ce que je vais résumer comme, ce n'est pas la façon dont il fonctionne parce que il ne crée pas une nouvelle instance chaque fois que j'exécuter ce code - cela crée seulement une référence à l'objet - qui est pourquoi il fonctionne une fois mais pas plusieurs fois. Donc, après un peu plus de lecture que je suis venu avec 3 façons possibles pour une résolution à mon problème.

1) Utiliser une technique pour créer une copie complète à un nouvel objet. Exemple d'autre question StackOverflow - objets de clonage profond

2) Stocker le XAML dans les chaînes dans l'application, puis utiliser le lecteur XAML pour créer des instances des chemins:

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) stocker uniquement les données de chemin dans la ressource dictionnaire. Créer une nouvelle instance d'un chemin dans le code, appliquer les données de chemin vers le nouveau chemin, puis ajoutez les autres propriétés que je suis intéressé par la main.

Le XAML - Les données de chemin est stocké sous forme 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>

Le code C # pour ensuite créer une instance et d'appliquer les autres valeurs:

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

Autres conseils

Il y a un moyen plus facile, moyen intégré pour le faire. Set x: Shared = "false" sur la ressource. Cela lui permettra d'être réutilisé. Ensuite, utilisez autant de fois que vous le souhaitez.

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

Il suffit de créer un style pour le chemin, et l'appliquer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top