web-dev-qa-db-fra.com

Définition de la source d'image WPF dans le code

J'essaie de définir la source d'une image WPF dans le code. L'image est incorporée en tant que ressource dans le projet. En regardant des exemples, j'ai trouvé le code ci-dessous. Pour une raison quelconque, cela ne fonctionne pas - l'image ne s'affiche pas.

En déboguant, je peux voir que le flux contient les données d'image. Alors, qu'est-ce qui ne va pas?

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;

L'icône est définie comme ceci: <Image x:Name="_icon" Width="16" Height="16" />

309
Torbjørn

Après avoir eu le même problème que vous et lu, j'ai découvert la solution - Pack URIs .

J'ai fait ce qui suit dans le code:

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;

Ou plus court, en utilisant un autre constructeur BitmapImage:

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

L'URI est divisé en parties:

  • Autorité: application:///
  • Chemin: nom d'un fichier de ressources compilé dans un assembly référencé. Le chemin doit être conforme au format suivant: AssemblyShortName[;Version][;PublicKey];component/Path

    • AssemblyShortName: nom abrégé de l'assembly référencé.
    • ; Version [facultatif]: version de l'assembly référencé contenant le fichier de ressources. Ceci est utilisé lorsque deux ou plusieurs assemblys référencés portant le même nom abrégé sont chargés.
    • ; PublicKey [facultatif]: clé publique utilisée pour signer l'assembly référencé. Ceci est utilisé lorsque deux ou plusieurs assemblys référencés portant le même nom abrégé sont chargés.
    • ; composant: spécifie que l'Assemblée à laquelle il est fait référence est référencée à partir de l'Assemblée locale.
    • / Chemin: nom du fichier de ressources, y compris son chemin, par rapport à la racine du dossier de projet de l'assembly référencé.

Les trois barres après application: doivent être remplacées par des virgules:

Remarque: Le composant autorité d'un URI de pack est un URI incorporé qui pointe vers un package et doit être conforme à la RFC 2396. De plus, le caractère "/" doit être remplacé par les caractères "," et réservés, tels que "%". et "?" doit être échappé. Voir le CPVP pour plus de détails.

Et bien sûr, assurez-vous de définir l'action de génération sur votre image sur Resource.

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

Cela chargera une image appelée "Untitled.png" dans un dossier appelé "Images" avec son "Action de construction" définie sur "Ressource" dans un assembly appelé "WpfApplication1".

170
Simon

C'est un peu moins de code et peut être fait en une seule ligne.

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

Très facile:

Pour définir dynamiquement l'image d'un élément de menu, procédez comme suit:

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

... alors que "icon.ico" peut être situé partout (il se trouve actuellement dans le répertoire "Ressources") et doit être lié en tant que ressource ...

41
A Bothe

Vous pouvez également réduire cela à une ligne. C'est le code que j'ai utilisé pour définir l'icône pour ma fenêtre principale. Il suppose que le fichier .ico est marqué en tant que contenu et qu'il est copié dans le répertoire de sortie.

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

Manière la plus simple:

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

As-tu essayé:

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

C'est mon chemin:

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

Usage:

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

Voici un exemple qui définit le chemin de l'image de manière dynamique (image située quelque part sur le disque plutôt que construite en tant que ressource):

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

Reflets sur les icônes ...

D'abord pensé, on pourrait penser que la propriété Icon ne peut contenir qu'une image. Mais il peut en réalité contenir n'importe quoi! J'ai découvert cela par accident lorsque j'ai essayé par programmation de définir la propriété Image directement sur une chaîne avec le chemin d'accès à une image. Le résultat était qu'il ne montrait pas l'image, mais le texte même du chemin!

Cela conduit à une alternative pour ne pas avoir à créer une image pour l'icône, mais utiliser du texte avec une police de symbole pour afficher une simple "icône". L'exemple suivant utilise le police Wingdings qui contient un symbole "floppydisk". Ce symbole est en réalité le caractère <, qui a une signification particulière en XAML. Nous devons donc utiliser la version codée &lt;. Cela fonctionne comme un rêve! Ce qui suit montre un symbole de disquette sous forme d’icône sur l’élément de menu:

<MenuItem Name="mnuFileSave" Header="Save" Command="ApplicationCommands.Save">
  <MenuItem.Icon>
    <Label VerticalAlignment="Center" HorizontalAlignment="Center" FontFamily="Wingdings">&lt;</Label>
  </MenuItem.Icon>
</MenuItem>
8
awe

Si votre image est stockée dans un ResourceDictionary, vous pouvez le faire avec une seule ligne de code:

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

Il y a aussi un moyen plus simple. Si l'image est chargée en tant que ressource dans le code XAML et que le code en question est le code-behind pour ce contenu XAML:

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

Placez le cadre dans un VisualBrush:

VisualBrush brush = new VisualBrush { TileMode = TileMode.None };

brush.Visual = frame;

brush.AlignmentX = AlignmentX.Center;
brush.AlignmentY = AlignmentY.Center;
brush.Stretch = Stretch.Uniform;

Placez le VisualBrush dans 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;

Maintenant, placez GeometryDrawing dans DrawingImage:

new DrawingImage(drawing);

Placez ceci sur votre source de l'image, et voilà!

Vous pouvez le faire beaucoup plus facilement cependant:

<Image>
    <Image.Source>
        <BitmapImage UriSource="/yourassembly;component/YourImage.PNG"></BitmapImage>
    </Image.Source>
</Image>

Et en code:

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

Il y a aussi un moyen plus simple. Si l'image est chargée en tant que ressource dans le XAML et que le code en question est le codebehind pour ce XAML:

Voici le dictionnaire de ressources pour un fichier XAML - la seule ligne qui compte pour vous est ImageBrush avec la clé "PosterBrush" - le reste du code consiste simplement à afficher le contexte

<UserControl.Resources>
        <ResourceDictionary>
            <ImageBrush x:Key="PosterBrush" ImageSource="..\Resources\Images\EmptyPoster.jpg" Stretch="UniformToFill"/>

        </ResourceDictionary>
    </UserControl.Resources>

Maintenant, dans le code derrière, vous pouvez simplement faire ceci

ImageBrush posterBrush = (ImageBrush)Resources["PosterBrush"];
3
Mark Mullin

Comment charger une image intégrée dans des icônes de ressources et des images (version corrigée d'Arcturus):

Supposons que vous vouliez ajouter un bouton avec une image. Que devrais tu faire?

  1. Ajoutez aux icônes du dossier du projet et placez l'image ClickMe.png ici
  2. Dans les propriétés de 'ClickMe.png', définissez 'BuildAction' sur 'Ressource'
  3. Supposons que le nom de votre assemblée compilée soit 'Company.ProductAssembly.dll'.
  4. Il est maintenant temps de charger notre image dans XAML

    <Button Width="200" Height="70">
      <Button.Content>
        <StackPanel>
          <Image Width="20" Height="20">
            <Image.Source>
              <BitmapImage UriSource="/Company.ProductAssembly;component/Icons/ClickMe.png"></BitmapImage>
              </Image.Source>
          </Image>
          <TextBlock HorizontalAlignment="Center">Click me!</TextBlock>
        </StackPanel>
      </Button.Content>
    </Button>
    

Terminé.

2
Siarhei Kuchuk

Je suis un nouveau sur WPF, mais pas sur .NET.

J'ai passé cinq heures à essayer d'ajouter un fichier PNG à un "Projet de bibliothèque de contrôles personnalisés WPF" dans .NET 3.5 (Visual Studio 2010) et à le définir comme arrière-plan d'un contrôle hérité d'une image.

Rien de relatif avec les URI n'a fonctionné. Je ne peux pas imaginer pourquoi il n’existe aucune méthode permettant d’obtenir un URI à partir d’un fichier de ressources, via IntelliSense, par exemple:

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

J'ai essayé beaucoup d'URI et joué avec ResourceManager, ainsi qu'avec les méthodes GetManifest de Assembly, mais il y avait toutes des exceptions ou des valeurs NULL.

Ici, je pot le code qui a fonctionné pour moi:

// 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;
2
JoanComasFdz

Vous venez de manquer un peu.

Pour obtenir une ressource incorporée à partir d'une assemblée, vous devez mentionner le nom de l'assembly avec votre nom de fichier, comme je l'ai mentionné ici:

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;
1
maulik kansara

Si vous avez déjà un flux et connaissez le format, vous pouvez utiliser quelque chose comme ceci:

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