2008-12-07 19 views
356

Vengo de un fondo en su mayoría web y un poco de Windows Forms. Para un nuevo proyecto, usaremos WPF. La aplicación WPF necesitará de 10 a 20 iconos pequeños e imágenes con fines ilustrativos. Estoy pensando en almacenarlos en el ensamblado como recursos integrados. ¿Es ese el camino correcto?WPF image resources

¿Cómo especifico en XAML que un control de imagen debe cargar la imagen desde un recurso incrustado?

Respuesta

421

Si va a utilizar la imagen en varios lugares, entonces vale la pena cargar los datos de imagen solo una vez en la memoria y luego compartirla entre todos los elementos Image.

Para ello, cree un BitmapSource como un recurso en alguna parte:

<BitmapImage x:Key="MyImageSource" UriSource="../Media/Image.png" /> 

Luego, en el código, usar algo como:

<Image Source="{StaticResource MyImageSource}" /> 

En mi caso, me di cuenta que tenía que establezca el archivo Image.png para tener una acción de compilación de Resource en lugar de solo Content. Esto hace que la imagen sea transportada dentro de su ensamblado compilado.

+5

¿Sería posible hacer esto de forma dinámica? Si tengo una cantidad diferente de imágenes que me gustaría cargar en la puesta en marcha, ¿podría crear un BitmapSource por imagen y referirme a ellas de la misma manera que la anterior? –

+2

@Becky - Sí, podría, aunque si quería referirse a ellos en Xaml, podría necesitar usar la extensión de marcado 'DynamicResource' en lugar de' StaticResource', suponiendo que conocería las claves en tiempo de compilación. En WPF puede crear diccionarios de recursos en tiempo de ejecución. De hecho, eso es lo que sucede cuando cargas un documento Xaml, es solo que no ves el equivalente de C#. –

+0

Gracias por la respuesta :) Me referiré a ellos a través de FindResource, pero creo que esto puede ahorrar una cantidad ridícula de procesamiento en mi aplicación ahora, así que gracias :) –

34

sí, es la manera correcta. Se podría utilizar la imagen en el archivo de recursos simplemente utilizando la ruta:

<Image Source="..\Media\Image.png" /> 

debe configurar la acción de compilación del archivo de imagen en "Recursos"

+1

Gracias por esto. ¿Hay alguna manera de hacer algo similar con ImageSource, esencialmente cargando la imagen una vez en un diccionario de recursos? Me temo que este enfoque carga los datos de imagen varias veces en la memoria. –

+2

Esto será un desastre cuando necesite refactorizar su código. Tendrá que cambiar manualmente todas las referencias de imagen si su documento xaml cambia el espacio de nombre. El método descrito por Drew Noakes es mucho más suave y fácil de mantener. –

2

Si está utilizando la mezcla, para que sea Es muy fácil y no tiene problemas para obtener la ruta correcta para el atributo Fuente, solo arrastre y suelte la imagen desde el panel Proyecto al diseñador.

150

me pareció ser la mejor práctica de la utilización de imágenes, vídeo, etc es:

  • Cambiar los archivos "Acción de generación" a "contenido". Asegúrese de revisar Copia para construir directorio
    • encuentra en el menú "Right-Click" en la ventana Explorador de soluciones
  • Fuente de la imagen en el siguiente formato:
    • "/ « YourAssemblyName »; componente /« YourPath »/ « YourImage.png »"

Ejemplo

<Image Source="/WPFApplication;component/Images/Start.png" /> 

Beneficios:

  • Los archivos no están integrados en el conjunto
    • El Administrador de recursos será levantar un poco de desbordamiento de memoria Pro blemas con demasiados recursos (en tiempo de compilación)
  • puede ser llamado entre los conjuntos
+28

Este mismo enfoque funciona si inserta el recurso en el ensamblado, pero tiene que establecer el " Build Action "to" Resource ". –

+4

Funciona, gracias. Una nota para los demás: se requiere "componente" "tal cual", "Imágenes" es una ruta relativa de png en el proyecto. Es decir. la imagen que se coloca en la raíz será "" – Badiboy

+3

Un ejemplo de cómo hacer esto en C# sería agradable. (Ese no es un URI válido, por lo que no se puede usar al construir un BitmapImage.) – Vaccano

41

Algunas personas están pidiendo hacer esto en el código y no conseguir un Answ er.

Después de pasar muchas horas buscando encontré un método muy simple, no encontré ningún ejemplo y entonces comparto el mío aquí que funciona con imágenes. (El mío era un .gif)

Resumen:

Devuelve un BitmapFrame cuales ImageSource "destinos" parece que les gusta.

Uso:

doGetImageSourceFromResource ("[YourAssemblyNameHere]", "[YourResourceNameHere]"); 

Método:

static internal ImageSource doGetImageSourceFromResource(string psAssemblyName, string psResourceName) 
{ 
    Uri oUri = new Uri("pack://application:,,,/" +psAssemblyName +";component/" +psResourceName, UriKind.RelativeOrAbsolute); 
    return BitmapFrame.Create(oUri); 
} 

Aprendizajes:

De mis experiencias la cadena de paquete no es el problema, un chequeo de las corrientes y sobre todo si la lectura de la primera vez ha establecido el puntero al final del archivo y necesita volver a establecerlo en cero antes de volver a leerlo.

¡Espero que esto le ahorre las muchas horas que deseo que esta pieza tenga para mí!

4
  1. Visual Studio 2010 Professional SP1.
  2. .NET Framework 4 Client Profile.
  3. Imagen PNG agregada como recurso en las propiedades del proyecto.
  4. Nuevo archivo en la carpeta Recursos creado automáticamente.
  5. Build action set to resource.

Esto funcionó para mí:

<BitmapImage x:Key="MyImageSource" UriSource="Resources/Image.png" /> 
35

En código para cargar un recurso en el montaje executiong donde mi imagen Freq.png estaba en la carpeta Icons y se define como Resource:

this.Icon = new BitmapImage(new Uri(@"pack://application:,,,/" 
    + Assembly.GetExecutingAssembly().GetName().Name 
    + ";component/" 
    + "Icons/Freq.png", UriKind.Absolute)); 

I también hizo una función si alguien puede usarlo:

/// <summary> 
/// Load a resource WPF-BitmapImage (png, bmp, ...) from embedded resource defined as 'Resource' not as 'Embedded resource'. 
/// </summary> 
/// <param name="pathInApplication">Path without starting slash</param> 
/// <param name="assembly">Usually 'Assembly.GetExecutingAssembly()'. If not mentionned, I will use the calling assembly</param> 
/// <returns></returns> 
public static BitmapImage LoadBitmapFromResource(string pathInApplication, Assembly assembly = null) 
{ 
    if (assembly == null) 
    { 
     assembly = Assembly.GetCallingAssembly(); 
    } 

    if (pathInApplication[0] == '/') 
    { 
     pathInApplication = pathInApplication.Substring(1); 
    } 
    return new BitmapImage(new Uri(@"pack://application:,,,/" + assembly.GetName().Name + ";component/" + pathInApplication, UriKind.Absolute)); 
} 

Uso (supuesto se pone la función en una clase ResourceHelper):

this.Icon = ResourceHelper.LoadBitmapFromResource("Icons/Freq.png"); 

Nota: ver MSDN Pack URIs in WPF:
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

+0

new Uri throws URI no válido: puerto no válido especificado. – Steve

+0

¿Tiene el uri ofensor? –

+0

mismo que el tuyo, excepto que el mío se estaba ejecutando dentro de un WPF alojado en Winform. Y el esquema "paquete" aún no estaba registrado cuando llamé al nuevo Uri. – Steve

-4

Esto funcionó

y las imágenes que se define es recursos en propiedades

var bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(MyProject.Properties.Resources.myImage.GetHbitmap(), 
             IntPtr.Zero, 
             Int32Rect.Empty, 
             BitmapSizeOptions.FromEmptyOptions()); 
    MyButton.Background = new ImageBrush(bitmapSource); 
img_username.Source = bitmapSource; 
+0

Sin ofender, pero esto huele a mala práctica. – ShloEmi