2010-12-08 17 views
8

Quiero reutilizar algún fragmento XAML como imagen en alguna aplicación/biblioteca de WPF.Imagen vectorial como fragmento XAML reutilizable

El fondo del problema es el siguiente:

Es fácil de reutilizar una imagen de mapa de bits en una aplicación de WPF. La imagen se puede agregar como un recurso, puedo usar <Image Source="packURI"/> en muchos lugares en XAML para que la imagen sea la misma.

Pero me gustaría tener la posibilidad de hacer lo mismo para una imagen vectorial. La imagen en sí misma se puede representar como Path, pero no puedo reutilizar el mismo Path como recurso, porque simplemente usarlo en varios lugares diferentes (y posiblemente desde varios subprocesos de IU) está prohibido (el elemento UI puede tener solo un padre lógico).

Por otra parte, la pregunta se vuelve más complicada si me gustaría construir la "imagen" de varios Path s, use un Canvas para ello. O algún código XAML arbitrario.

He intentado utilizar un Style para la Path, por lo que la imagen se representa de tal manera:

<Path Style={StaticResource VectorImage1}/> 

Ésta parece ser una forma reutilizable, pero me preocupan dos problemas:

  1. Si la implementación de una imagen vectorial se cambia de Path a (por ejemplo) Canvas, tendré que reemplazarla no solo en el estilo, sino en todas partes del código fuente que lo usa.
  2. La definición de una ruta utilizando un estilo parece ser demasiado detallada.
  3. No veo forma de generalizar este enfoque para usar Canvas o código XAML arbitrario.
  4. La sintaxis parece ser bastante antinatural.

Hay otra manera de tener un fragmento XAML reutilizable, a través de la definición de un UserControl, pero la definición de un control de usuario separada cada vector por parece ser una exageración.

¿Existe una manera mejor, agradable y correcta de definir un fragmento XAML reutilizable?

Respuesta

14

Puede agregar el atributo x: Shared al recurso de ruta de acceso y utilizarlo como StaticResource. Esto funcionará si los cambios "MyVectorImage" a algo más

actualización
Probablemente es mejor utilizar un ContentControl o similares como para ser capaz de añadir propiedades tales como el margen 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> 

Ejemplo. Reemplaza "MyVectorImage" con un StackPanel que contiene dos rutas.

<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

Intenté usar su sugerencia, pero en el tiempo de ejecución recibí una excepción: "Atributo compartido en el espacio de nombres" http: //schemas.microsoft.com/winfx/2006/xaml 'solo se puede usar en diccionarios de recursos compilados. " Moví 'MyVectorImage' a un diccionario de recursos XAML separado, pero recibo el mismo mensaje de error cuando incluyo ese diccionario en los MergedDictionaries de la ventana. – Vlad

+0

@ Vlad @ I actualicé mi ejemplo. Si probamos el ejemplo con el StackPanel, olvidé mover el atributo x: Shared al StackPanel. –

+0

Veo, mi mal, debería haber intentado entender leer exactamente lo que dice el mensaje. Con x: compartido solo en el nivel superior, funciona. – Vlad

3

Puede almacenar la ruta en un diccionario de recursos y establecer x: Compartida en false:

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

Esto le dirá WPF para crear una nueva instancia cada vez que se solicita. http://msdn.microsoft.com/en-us/library/aa970778.aspx

+0

¿funcionará esto para fragmentos arbitrarios de WPF? Por ejemplo, 'Canvas' con subelementos? – Vlad

+0

muchas gracias; su sugerencia es básicamente la misma que la aceptada. – Vlad

+0

gracias por explicar lo que shared = false realmente hace, resolvió mi problema – EdwardM

5

Después de algunas investigaciones, existe una opción más: el uso de un DrawingImage como Source para una imagen. La fuente de imagen habitual es BitmapSource, sin embargo, también puede ser "gráficos vectoriales".

Aquí es 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> 

produce una imagen agradable del vector tales:

vector image from the source above

Sin embargo, otra opción podría estar utilizando un DrawingBrush, al igual que en esta cuestión de forma: How to store and retrieve multiple shapes in XAML/WPF?.

+1

Prefiero este enfoque, pero creo que la respuesta se beneficiaría de algunos ejemplos de código en línea. El uso de un DrawingImage le permite combinar múltiples gráficos vectoriales (y múltiples colores) en un solo icono cohesivo, utilizando el elemento como propiedad del contenido de DrawingImage. También le permite, en su código de UI, usar siempre un elemento para sus iconos, independientemente de si se refiere a una imagen vectorial o a una imagen de mapa de bits; la propiedad "Fuente" se referirá al recurso vectorial DrawingImage o al recurso de imagen BitmapSource. – BTownTKD

+0

@BTownTKD: tiene razón, intentaré construir algunos ejemplos – Vlad

+0

El enlace de ejemplo está roto y no se puede recuperar. (El contenido de MSDN para ese miembro no tiene ningún ejemplo.) ¿Alguien tiene contenido para compartir en este sitio? – ygoe

Cuestiones relacionadas