Configurar fuente de imagen WPF en código

Estoy tratando de establecer una fuente de imagen WPF en el código. La imagen está integrada como un recurso en el proyecto. Al mirar ejemplos, he encontrado el siguiente código. Por alguna razón, no funciona: la imagen no aparece.

Al depurar, puedo ver que la transmisión contiene los datos de la imagen. ¿Así que qué hay de malo?

Assembly asm = Assembly.GetExecutingAssembly(); Stream iconStream = asm.GetManifestResourceStream("SomeImage.png"); PngBitmapDecoder iconDecoder = new PngBitmapDecoder(iconStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); ImageSource iconSource = iconDecoder.Frames[0]; _icon.Source = iconSource; 

El icono se define de la siguiente manera:

Después de tener el mismo problema que tú y leer un poco, descubrí la solución – Pack URI .

Hice lo siguiente en el código:

 Image finalImage = new Image(); finalImage.Width = 80; ... BitmapImage logo = new BitmapImage(); logo.BeginInit(); logo.UriSource = new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png"); logo.EndInit(); ... finalImage.Source = logo; 

O más corto, usando otro constructor de BitmapImage:

 finalImage.Source = new BitmapImage( new Uri("pack://application:,,,/AssemblyName;component/Resources/logo.png")); 

El URI está dividido en partes:

  • Autoridad: application:///
  • Ruta: el nombre de un archivo de recursos que se comstack en un ensamblado al que se hace referencia. La ruta debe ajustarse al siguiente formato: AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName: el nombre corto para el conjunto al que se hace referencia.
    • ; Versión [opcional]: la versión del ensamblado al que se hace referencia que contiene el archivo de recursos. Esto se usa cuando se cargan dos o más ensambles referenciados con el mismo nombre corto.
    • ; PublicKey [opcional]: la clave pública que se utilizó para firmar el ensamblado al que se hace referencia. Esto se usa cuando se cargan dos o más ensambles referenciados con el mismo nombre corto.
    • ; componente: especifica que el conjunto al que se hace referencia se referencia desde el ensamblado local.
    • / Ruta: el nombre del archivo de recursos, incluida su ruta, relativo a la raíz de la carpeta de proyectos del ensamblaje al que se hace referencia.

Las tres barras inclinadas después de la application: deben ser reemplazadas por comas:

Nota: El componente de autoridad de un URI de paquete es un URI incrustado que apunta a un paquete y debe cumplir con RFC 2396. Además, el carácter “/” debe reemplazarse con el carácter “,” y los caracteres reservados como “%” y “?” debe ser escapado. Vea el OPC para más detalles.

Y, por supuesto, asegúrese de establecer la acción de comstackción en su imagen en el Resource .

 var uriSource = new Uri(@"/WpfApplication1;component/Images/Untitled.png", UriKind.Relative); foo.Source = new BitmapImage(uriSource); 

Esto cargará una imagen llamada “Untitled.png” en una carpeta llamada “Imágenes” con su “Acción de comstackción” establecida en “Recurso” en un ensamble llamado “WpfApplication1”.

Este es un código un poco menos y se puede hacer en una sola línea.

 string packUri = "pack://application:,,,/AssemblyName;component/Images/icon.png"; _image.Source = new ImageSourceConverter().ConvertFromString(packUri) as ImageSource; 

Muy fácil:

Para establecer dinámicamente la imagen de un elemento de menú, solo haga lo siguiente:

 MyMenuItem.ImageSource = new BitmapImage(new Uri("Resource/icon.ico",UriKind.Relative)); 

… mientras que “icon.ico” puede ubicarse en todas partes (actualmente se encuentra en el directorio ‘Recursos’) y debe estar vinculado como Recurso …

También puedes reducir esto a una línea. Este es el código que utilicé para configurar el icono para mi ventana principal. Supone que el archivo .ico está marcado como Contenido y se está copiando en el directorio de salida.

  this.Icon = new BitmapImage(new Uri("Icon.ico", UriKind.Relative)); 

Has probado:

 Assembly asm = Assembly.GetExecutingAssembly(); Stream iconStream = asm.GetManifestResourceStream("SomeImage.png"); BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = iconStream; bitmap.EndInit(); _icon.Source = bitmap; 

La manera más simple:

 var uriSource = new Uri("image path here"); image1.Source = new BitmapImage(uriSource); 

Esta es mi manera:

 internal static class ResourceAccessor { public static Uri Get(string resourcePath) { var uri = string.Format( "pack://application:,,,/{0};component/{1}" , Assembly.GetExecutingAssembly().GetName().Name , resourcePath ); return new Uri(uri); } } 

Uso:

 new BitmapImage(ResourceAccessor.Get("Images/1.png")) 

Aquí hay un ejemplo que establece la ruta de la imagen de forma dinámica (imagen ubicada en algún lugar del disco en lugar de comstackr como recurso):

 if (File.Exists(imagePath)) { // Create image element to set as icon on the menu element Image icon = new Image(); BitmapImage bmImage = new BitmapImage(); bmImage.BeginInit(); bmImage.UriSource = new Uri(imagePath, UriKind.Absolute); bmImage.EndInit(); icon.Source = bmImage; icon.MaxWidth = 25; item.Icon = icon; } 

Reflexiones sobre los icons …

Primero, pensaría que la propiedad Icon solo puede contener una imagen. ¡Pero en realidad puede contener cualquier cosa! Descubrí esto por accidente cuando programé establecer la propiedad de la Image directamente a una cadena con la ruta a una imagen. El resultado fue que no mostró la imagen, ¡sino el texto real de la ruta!

Esto lleva a una alternativa para no tener que hacer una imagen para el icono, sino que usa texto con una fuente de símbolo para mostrar un simple “icono”. El siguiente ejemplo usa la fuente Wingdings que contiene un símbolo “floppydisk”. Este símbolo es realmente el carácter < , que tiene un significado especial en XAML, por lo que debemos usar la versión codificada < en lugar. Esto funciona como un sueño! A continuación, se muestra un símbolo floppydisk como un ícono en el elemento del menú:

      

También hay una manera más simple. Si la imagen se carga como un recurso en el XAML, y el código en cuestión es el código subyacente para ese contenido XAML:

 Uri iconUri = new Uri("pack://application:,,,/ImageNAme.ico", UriKind.RelativeOrAbsolute); NotifyIcon.Icon = BitmapFrame.Create(iconUri); 

Si su imagen está almacenada en un ResourceDictionary, puede hacerlo con solo una línea de código:

 MyImage.Source = MyImage.FindResource("MyImageKeyDictionary") as ImageSource; 

Pon el marco en un VisualBrush:

 VisualBrush brush = new VisualBrush { TileMode = TileMode.None }; brush.Visual = frame; brush.AlignmentX = AlignmentX.Center; brush.AlignmentY = AlignmentY.Center; brush.Stretch = Stretch.Uniform; 

Coloque VisualBrush en GeometryDrawing

 GeometryDrawing drawing = new GeometryDrawing(); drawing.Brush = brush; // Brush this in 1, 1 ratio RectangleGeometry rect = new RectangleGeometry { Rect = new Rect(0, 0, 1, 1) }; drawing.Geometry = rect; 

Ahora coloque el GeometryDrawing en una DrawingImage:

 new DrawingImage(drawing); 

Coloque esto en su fuente de la imagen, y ¡voilà!

Sin embargo, podrías hacerlo mucho más fácil:

      

Y en código:

 BitmapImage image = new BitmapImage { UriSource="/yourassembly;component/YourImage.PNG" }; 

También hay una manera más simple. Si la imagen se carga como un recurso en el XAML, y el código en cuestión es el código subyacente para ese XAML:

Aquí está el diccionario de recursos para un archivo XAML: la única línea que le interesa es ImageBrush con la clave “PosterBrush”: el rest del código es solo para mostrar el contexto.

      

Ahora, en el código detrás, puedes hacer esto

 ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"]; 

Cómo cargar una imagen desde incrustado en íconos e imágenes de recursos (versión corregida de Arcturus):

Supongamos que desea agregar un botón con una imagen. ¿Qué deberías hacer?

  1. Agregar a los icons de la carpeta del proyecto y poner la imagen ClickMe.png aquí
  2. En las propiedades de ‘ClickMe.png’, configure ‘BuildAction’ en ‘Resource’
  3. Supongamos que su nombre de ensamblado comstackdo es ‘Company.ProductAssembly.dll’.
  4. Ahora es el momento de cargar nuestra imagen en XAML

      

Hecho.

Soy nuevo en WPF, pero no en .NET.

Pasé cinco horas tratando de agregar un archivo PNG a un “Proyecto de biblioteca de control personalizado de WPF” en .NET 3.5 (Visual Studio 2010) y configurándolo como fondo de un control heredado de imagen.

Nada relativo con URI funcionó. No puedo imaginar por qué no hay un método para obtener un URI de un archivo de recursos, a través de IntelliSense, tal vez como:

 Properties.Resources.ResourceManager.GetURI("my_image"); 

Probé muchos URI y jugué con ResourceManager y los métodos GetManifest de Assembly, pero todos tenían excepciones o valores NULL.

Aquí meto el código que funcionó para mí:

 // Convert the image in resources to a Stream Stream ms = new MemoryStream() Properties.Resources.MyImage.Save(ms, ImageFormat.Png); // Create a BitmapImage with the stream. BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = ms; bitmap.EndInit(); // Set as source Source = bitmap; 

Si ya tiene una transmisión y conoce el formato, puede usar algo como esto:

 static ImageSource PngStreamToImageSource (Stream pngStream) { var decoder = new PngBitmapDecoder(pngStream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); return decoder.Frames[0]; } 

Te perdiste un poco.

Para obtener un recurso incrustado de cualquier ensamblado, debe mencionar el nombre del ensamblado con su nombre de archivo como mencioné aquí:

 Assembly asm = Assembly.GetExecutingAssembly(); Stream iconStream = asm.GetManifestResourceStream(asm.GetName().Name + "." + "Desert.jpg"); BitmapImage bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.StreamSource = iconStream; bitmap.EndInit(); image1.Source = bitmap;