2010-12-08 3 views
8

Je souhaite réutiliser un fragment XAML en tant qu'image dans une application/bibliothèque WPF.Image vectorielle en tant que fragment XAML réutilisable

Le fond du problème est le suivant:

Il est facile de réutiliser une image bitmap dans une application WPF. L'image peut être ajoutée en tant que ressource, je peux utiliser <Image Source="packURI"/> à de nombreux endroits dans XAML afin que l'image soit la même.

Mais j'aimerais avoir la possibilité de faire la même chose pour une image vectorielle. L'image elle-même peut être représentée comme Path, mais je ne peux pas réutiliser la même Path comme ressource, car il est interdit de l'utiliser à plusieurs endroits différents (et éventuellement à partir de plusieurs threads d'interface utilisateur) (l'élément UI ne peut avoir qu'un seul parent logique).

En outre, la question devient plus compliquée si je voudrais construire le "image" à partir de plusieurs Path s, utilisez un Canvas pour cela. Ou un code XAML arbitraire.

J'ai essayé d'utiliser un Style pour la Path, de sorte que l'image est représentée de manière:

<Path Style={StaticResource VectorImage1}/> 

Cela semble être un moyen réutilisable, mais je suis préoccupé par deux problèmes:

  1. Si l'implémentation d'une image vectorielle passe de Path à (par exemple) Canvas, je devrai le remplacer non seulement dans le style, mais partout dans le code source qui l'utilise.
  2. La définition d'un chemin utilisant un style semble être trop verbeuse.
  3. Je ne vois aucun moyen de généraliser cette approche pour l'utilisation Canvas ou un code XAML arbitraire.
  4. La syntaxe semble être plutôt artificielle.

Il y a d'autre moyen d'avoir un fragment de XAML réutilisable, en définissant un UserControl, mais la définition d'un contrôle utilisateur distinct pour chaque image vectorielle semble être un surpuissant.

Existe-t-il une meilleure façon de définir un fragment XAML réutilisable?

Répondre

14

Vous pouvez ajouter l'attribut x: Shared à la ressource Path et l'utiliser en tant que StaticResource. Cela fonctionnera si les modifications de « MyVectorImage » à quelque chose d'autre

Mise à jour
probablement mieux d'utiliser un ContentControl ou similaire à être en mesure d'ajouter des propriétés, telles que les marges, etc.

<Window.Resources> 
    <Path x:Key="MyVectorImage" 
      x:Shared="False" 
      Stroke="DarkGoldenRod" 
      StrokeThickness="3" 
      Data="M 10,20 C 10,25 40,35 40,17 H 28" 
      Stretch="Fill" 
      Width="100" 
      Height="40"/> 
</Window.Resources> 
<StackPanel> 
    <ContentControl Margin="10" Content="{StaticResource MyVectorImage}"/> 
    <ContentControl Margin="10" Content="{StaticResource MyVectorImage}"/> 
</StackPanel> 

Exemple. Vous remplacez "MyVectorImage" avec un StackPanel contenant deux chemins.

<Window.Resources> 
    <StackPanel x:Key="MyVectorImage" 
       x:Shared="False"> 
     <Path Stroke="DarkGoldenRod" 
       StrokeThickness="3" 
       Data="M 10,20 C 10,25 40,35 40,17 H 28" 
       Stretch="Fill" 
       Width="100" 
       Height="40"/> 
     <Path Stroke="DarkGoldenRod" 
       StrokeThickness="3" 
       Data="M 10,20 C 10,25 40,35 40,17 H 28" 
       Stretch="Fill" 
       Width="100" 
       Height="40"/> 
    </StackPanel> 
</Window.Resources> 
+1

J'ai essayé d'utiliser votre suggestion, mais à l'exécution, je reçois une exception: "Attribut partagé dans l'espace de noms" http: //schemas.microsoft.com/winfx/2006/xaml 'peut être utilisé uniquement dans les dictionnaires de ressources compilés. " J'ai déplacé 'MyVectorImage' dans un dictionnaire de ressources XAML séparé, mais j'ai le même message d'erreur lorsque j'inclue ce dictionnaire dans les Dictionnaires Merged de Windows. – Vlad

+0

@ Vlad @ J'ai mis à jour mon exemple. Si vous avez essayé l'exemple avec le StackPanel, j'avais oublié de déplacer l'attribut x: Shared vers le StackPanel. –

+0

Je vois, ma mauvaise, j'aurais dû essayer de comprendre lire ce que le message dit exactement. Avec x: Partagé uniquement au niveau supérieur, cela fonctionne. – Vlad

3

Vous pouvez stocker le chemin dans un dictionnaire de ressources et définir x: Partagé false:

<Path x:Key="CrossPath" 
     x:Shared="false" 
     ... 
     /> 

Ceci va dire WPF pour créer une nouvelle instance à chaque fois qu'il est demandé. http://msdn.microsoft.com/en-us/library/aa970778.aspx

+0

? Par exemple, 'Canvas' avec des sous-éléments? – Vlad

+0

merci beaucoup; votre suggestion est fondamentalement la même que la réponse acceptée. – Vlad

+0

merci d'expliquer ce que shared = false fait, il a résolu mon problème – EdwardM

5

Après quelques recherches, il y a une autre option: utiliser un DrawingImage comme Source pour une image. La source d'image habituelle est un BitmapSource, mais il peut aussi s'agir de "graphiques vectoriels".

Voici an example:

<Image> 
    <Image.Source> 
    <DrawingImage PresentationOptions:Freeze="True"> 
     <DrawingImage.Drawing> 
     <GeometryDrawing> 
      <GeometryDrawing.Geometry> 
      <GeometryGroup> 
       <EllipseGeometry Center="50,50" RadiusX="45" RadiusY="20" /> 
       <EllipseGeometry Center="50,50" RadiusX="20" RadiusY="45" /> 
      </GeometryGroup> 
      </GeometryDrawing.Geometry> 
      <GeometryDrawing.Brush> 
      <LinearGradientBrush> 
       <GradientStop Offset="0.0" Color="Blue" /> 
       <GradientStop Offset="1.0" Color="#CCCCFF" /> 
      </LinearGradientBrush> 
      </GeometryDrawing.Brush> 
      <GeometryDrawing.Pen> 
      <Pen Thickness="10" Brush="Black" /> 
      </GeometryDrawing.Pen> 
     </GeometryDrawing> 
     </DrawingImage.Drawing> 
    </DrawingImage> 
    </Image.Source> 
</Image> 

produit une telle belle image vectorielle:

vector image from the source above

Une autre option pourrait être l'aide d'un DrawingBrush, comme dans cette question SO: How to store and retrieve multiple shapes in XAML/WPF?. Est-ce que cela fonctionnera pour des fragments arbitraires de WPF?

+1

Je préfère cette approche, mais je pense que la réponse bénéficierait de certains exemples de code en ligne. L'utilisation d'une image DrawingImage vous permet de combiner plusieurs graphiques vectoriels (et plusieurs couleurs) en une seule icône cohérente en utilisant l'élément en tant que propriété de contenu de DrawingImage. Il vous permet également - dans votre code d'interface utilisateur - d'utiliser toujours un élément pour vos icônes, qu'il s'agisse d'une image vectorielle ou d'une image bitmap; la propriété "Source" fera référence à la ressource vectorielle DrawingImage ou à la ressource image BitmapSource. – BTownTKD

+0

@BTownTKD: vous avez raison, je vais essayer de construire quelques exemples – Vlad

+0

Exemple de lien est cassé et ne peut pas être récupéré. (Le contenu MSDN pour ce membre n'a aucun exemple.) Quelqu'un a-t-il du contenu à partager sur ce site? – ygoe

Questions connexes