433 votes

Stockage des ressources d'images WPF

Pour une application WPF qui aura besoin de 10 à 20 petites icônes et images à des fins d'illustration, le stockage de celles-ci dans l'assemblage en tant que ressources intégrées est-il la bonne solution ?

Si c'est le cas, comment puis-je spécifier dans XAML qu'un contrôle Image doit charger l'image à partir d'une ressource intégrée ?

494voto

Drew Noakes Points 69288

Si vous comptez utiliser l'image à plusieurs endroits, il est intéressant de ne charger les données de l'image qu'une seule fois en mémoire et de les partager ensuite entre tous les utilisateurs. Image éléments.

Pour ce faire, créez un BitmapSource comme une ressource quelque part :

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

Ensuite, dans votre code, utilisez quelque chose comme :

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

Dans mon cas, j'ai constaté que je devais définir le paramètre Image.png pour avoir une action de construction de Resource plutôt que juste Content . L'image est ainsi transportée dans votre assemblage compilé.

7 votes

Serait-il possible de faire cela de manière dynamique ? Si je dispose d'un nombre différent d'images que je souhaite charger au démarrage, pourrais-je créer un BitmapSource par image et y faire référence de la même manière que ci-dessus ?

2 votes

@Becky - Oui, vous pouvez le faire, mais si vous voulez vous y référer dans Xaml, vous devrez peut-être utiliser l'attribut DynamicResource au lieu de l'extension de balisage StaticResource en supposant que vous connaissez les clés au moment de la compilation. Dans WPF, vous pouvez créer des dictionnaires de ressources au moment de l'exécution. En fait, c'est ce qui se passe lorsque vous chargez un document Xaml, c'est juste que vous ne voyez pas l'équivalent en C#.

0 votes

Merci pour la réponse :) Je vais les référencer via FindResource, mais je pense que cela peut économiser une quantité ridicule de traitement dans mon application maintenant, donc merci :)

193voto

Nuno Rodrigues Points 792

J'ai trouvé que la meilleure pratique d'utilisation des images, des vidéos, etc. est :

  • Modifiez vos fichiers "Action de construction" a "Contenu" . N'oubliez pas de vérifier Copier dans le répertoire de construction .
    • Se trouve dans le menu "Clic droit" de la fenêtre de l'explorateur de solutions.
  • Source d'image dans le format suivant :
    • "/ "Votre nom d'assemblée" ;composant/"VotrePath"/ "VotreImage.png" "

Exemple

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

Avantages :

  • Les fichiers ne sont pas intégrés dans l'assemblage.
    • Le gestionnaire de ressources soulèvera quelques problèmes de débordement de mémoire avec trop de ressources (au moment de la construction).
  • Peut être appelé entre les assemblées.

37 votes

La même approche fonctionne si vous intégrez la ressource dans l'assemblage, mais vous devez définir l'"Action de construction" sur "Ressource".

5 votes

Ça marche, merci. Une remarque pour les autres : "composant" est requis "tel quel", "Images" est un chemin relatif de png dans le projet. Par exemple, l'image qui est placée dans la racine sera "<Image Source="/WPFApplication;component/Start.png" />".

4 votes

Un exemple de comment faire cela en C# serait bien (ce n'est pas un URI valide donc il ne peut pas être utilisé lors de la construction d'un BitmapImage).

48voto

Craig Points 251

Certaines personnes posent des questions sur la façon de faire cela en code et n'obtiennent pas de réponse.

Après avoir passé de nombreuses heures à chercher, j'ai trouvé une méthode très simple, je n'ai trouvé aucun exemple et je partage donc le mien ici qui fonctionne avec des images. (la mienne était un .gif)

Résumé :

Il renvoie un BitmapFrame que les "destinations" ImageSource semblent apprécier.

Utilisez :

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

Méthode :

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

Apprentissages :

D'après mon expérience, la chaîne de caractères n'est pas le problème, vérifiez vos flux et surtout si la première lecture a placé le pointeur à la fin du fichier et que vous devez le remettre à zéro avant de relire. à la fin du fichier et que vous devez le remettre à zéro avant de le lire à nouveau.

J'espère que cela vous épargnera les nombreuses heures que j'aurais souhaité que cette pièce ait pour moi !

46voto

Eric Ouellet Points 1370

Dans le code pour charger une ressource dans l'assemblage exécutant où mon image Freq.png était dans le dossier Icons et défini comme suit Resource :

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

J'ai également créé une fonction :

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

Utilisation (dans l'hypothèse où vous placez la fonction dans une classe ResourceHelper) :

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

Note : voir MSDN Pack URIs dans WPF :
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

0 votes

New Uri throws Invalid URI : Invalid port specified.

0 votes

Avez-vous l'uri incriminé ?

1 votes

Même uri que le vôtre, sauf que le mien s'exécute dans un WPF hébergé par Winform. Et le schéma "pack" n'était pas encore enregistré lorsque j'ai appelé new Uri.

44voto

ema Points 2346

Oui, c'est le bon chemin.

Vous pouvez utiliser l'image dans le fichier de ressources en utilisant simplement le chemin :

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

Vous devez définir l'action de construction du fichier image sur "Resource".

1 votes

Merci pour cela. Existe-t-il un moyen de faire quelque chose de similaire avec une ImageSource, en chargeant essentiellement l'image une fois dans un dictionnaire de ressources. Je crains que cette approche ne charge les données de l'image plusieurs fois en mémoire.

2 votes

Ce sera un véritable gâchis lorsque vous devrez refactoriser votre code. Vous devrez modifier manuellement toutes les références d'images si votre document xaml change d'espace de noms. La méthode décrite par Drew Noakes est beaucoup plus souple et plus facile à utiliser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X