Risorse immagine WPF


408

Vengo da uno sfondo prevalentemente Web e Windows Forms. Per un nuovo progetto, utilizzeremo WPF. L'applicazione WPF avrà bisogno di 10-20 piccole icone e immagini a scopo illustrativo. Sto pensando di archiviarli nell'assembly come risorse incorporate. È la strada giusta da percorrere?

Come faccio a specificare in XAML che un controllo Image dovrebbe caricare l'immagine da una risorsa incorporata?

Risposte:


473

Se utilizzerai l'immagine in più punti, vale la pena caricare i dati dell'immagine solo una volta in memoria e condividerli tra tutti gli Imageelementi.

Per fare ciò, crea un BitmapSource come risorsa da qualche parte:

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

Quindi, nel tuo codice, usa qualcosa come:

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

Nel mio caso, ho scoperto che dovevo impostare il Image.pngfile in modo che avesse un'azione di build Resourceanziché solo Content. Questo fa sì che l'immagine venga trasportata all'interno dell'assieme compilato.


6
Sarebbe possibile farlo in modo dinamico? Se ho un numero diverso di immagini che vorrei caricare all'avvio, posso creare una BitmapSource per immagine e fare riferimento ad esse allo stesso modo di cui sopra?
Becky Franklin,

2
@Becky - Sì, ma se volessi farvi riferimento in Xaml, potresti aver bisogno di usare l' DynamicResourceestensione di markup invece di StaticResource, supponendo che tu conoscessi le chiavi in ​​fase di compilazione. In WPF è possibile creare dizionari di risorse in fase di esecuzione. In effetti, è quello che succede quando carichi un documento Xaml, è solo che non vedi l'equivalente C #.
Drew Noakes,

9
Qualcosa che ho colpito: se aggiungi la tua risorsa di immagine a un dizionario di risorse, non dimenticare di fare riferimento a quel dizionario di immagini in XAML per il tuo componente. Qualcosa di simile: <UserControl.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source = "Dictionary1.xaml" /> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </UserControl.Resources>
Dan Mitchell

4
Di solito aggiungo Width="{Binding Source.PixelWidth, RelativeSource={RelativeSource Self}}" a Image, poiché altrimenti vedo spesso le immagini ingrandirsi in modo grottesco per qualche motivo (come le icone 16x16 allungate a qualcosa che assomiglia a 200x200 pixel).
OR Mapper

5
Ho scoperto che se BitmapImage è dichiarato in risorse risorse di un assembly di riferimento, UriSource deve essere un pacchettoURI affinché funzioni. Altrimenti, vedrai che puoi vedere l'immagine nel tuo editor xaml in VS ma nessuna immagine durante il debug. Confezione URIS: msdn.microsoft.com/en-au/library/aa970069(v=vs.100).aspx
failedprogramming

174

Ho scoperto che la migliore pratica di utilizzo di immagini, video, ecc. È:

  • Modifica i tuoi file "Crea azione" in "Contenuto" . Assicurati di selezionare Copia per compilare la directory .
    • Si trova nel menu "Fai clic con il tasto destro" nella finestra Esplora soluzioni.
  • Fonte immagine nel seguente formato:
    • "/ « YourAssemblyName » ; component /« YourPath »/ « YourImage.png » "

Esempio

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

Benefici:

  • I file non sono incorporati nell'assieme.
    • Il gestore risorse solleverà alcuni problemi di overflow della memoria con troppe risorse (al momento della creazione).
  • Può essere chiamato tra assiemi.

36
Questo stesso approccio funziona se si incorpora la risorsa nell'assembly, ma è necessario impostare "Build Action" su "Resource".
Ashley Davis,

5
Funziona grazie. Una nota per gli altri: "componente" è richiesto "così com'è", "Immagini" è un percorso relativo di png nel progetto. Vale a dire che l'immagine che viene inserita nella radice sarà "<Image Source =" / WPFApplication; component / Start.png "/>"
Badiboy,

3
Un esempio di come farlo in C # sarebbe bello. (Questo non è un URI valido, quindi non può essere usato quando si costruisce un'immagine Bitmap.)
Vaccano,

5
Quindi, come si fa se il file è impostato su Embedded Resource? Questo non sembra funzionare. E non voglio includere l'immagine nel mio progetto due volte. (Lo sto già utilizzando come risorsa incorporata.)
BrainSlugs83

2
Dove e come "componente" entra nel percorso. Fa parte di alcune specifiche?
Triynko,

46

Alcune persone chiedono di farlo nel codice e di non ottenere una risposta.

Dopo aver trascorso molte ore a cercare ho trovato un metodo molto semplice, non ho trovato alcun esempio e quindi condivido il mio qui che funziona con le immagini. (il mio era un .gif)

Sommario:

Restituisce un BitmapFrame che le "destinazioni" di ImageSource sembrano gradire.

Uso:

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

Metodo:

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

apprendimenti:

Dalla mia esperienza, la stringa del pacchetto non è un problema, controlla i tuoi stream e soprattutto se leggendolo la prima volta hai impostato il puntatore alla fine del file e devi reimpostarlo su zero prima di rileggerlo.

Spero che questo ti salvi le molte ore che vorrei che questo pezzo avesse per me!


44

Nel codice per caricare una risorsa nell'assembly in esecuzione in cui la mia immagine Freq.pngera nella cartella Iconse definita come Resource:

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

Ho anche fatto una funzione:

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

Utilizzo (si supponga di inserire la funzione in una classe ResourceHelper):

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

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


nuovo Uri genera URI non valido: porta specificata non valida.
Steve

Hai l'uri offensivo?
Eric Ouellet,

1
stesso urlo del tuo tranne che il mio era in esecuzione all'interno di una winform ospitata da WPF. E lo schema "pack" non era ancora registrato quando ho chiamato il nuovo Uri.
Steve

1
Oops ... probabilmente è stato ritirato in winform ospitato WPF. Mi dispiace. Non proverò a ripararlo perché penso che non sia un uso molto comune. In bocca al lupo!
Eric Ouellet,

Nel mio caso, new Uri(@"pack://application:,,,/" + pathInApplication)anche usare ha fatto il trucco.
Adam Calvet Bohl,

40

Sì, è nel modo giusto.

È possibile utilizzare l'immagine nel file di risorse semplicemente usando il percorso:

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

È necessario impostare l'azione di compilazione del file immagine su "Risorsa".


1
Grazie per questo. C'è un modo per fare qualcosa di simile con un ImageSource, essenzialmente caricando l'immagine una volta in un dizionario delle risorse. Temo che questo approccio carichi i dati dell'immagine più volte in memoria.
Drew Noakes,

2
Questo sarà un disastro quando dovrai refactificare il tuo codice. Dovrai cambiare manualmente tutti i riferimenti alle immagini se il tuo documento xaml cambia spazio di nomi. Il metodo descritto da Drew Noakes è molto più fluido e stabile.
Kasper Holdum,

14

Descrizione completa su come utilizzare le risorse: risorse dell'applicazione WPF, contenuto e file di dati

E come fare riferimento a questi, leggi "Pack URIs in WPF".

In breve, esistono persino mezzi per fare riferimento a risorse provenienti da assiemi referenziati / referenziati.


Il link sembra essere attivo e funzionante (anche se dice "Questa documentazione è archiviata e non viene mantenuta" ).
Peter Mortensen,

5
  1. Visual Studio 2010 Professional SP1.
  2. Profilo client .NET Framework 4.
  3. Immagine PNG aggiunta come risorsa sulle proprietà del progetto.
  4. Nuovo file nella cartella Risorse creato automaticamente.
  5. Crea azione impostata su risorsa.

Questo ha funzionato per me:

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

3

Se stai usando Blend , per renderlo ancora più semplice e non avere problemi a ottenere il percorso corretto per l' attributo Source , trascina e rilascia l'immagine dal pannello Progetto sul designer.


3

Sì, è nel modo giusto. È possibile utilizzare le immagini nel file di risorse utilizzando un percorso:

<StackPanel Orientation="Horizontal">
    <CheckBox  Content="{Binding Nname}" IsChecked="{Binding IsChecked}"/>
    <Image Source="E:\SWorking\SharePointSecurityApps\SharePointSecurityApps\SharePointSecurityApps.WPF\Images\sitepermission.png"/>
    <TextBlock Text="{Binding Path=Title}"></TextBlock>
</StackPanel>

-5

Il seguente ha funzionato e le immagini da impostare sono risorse nelle proprietà:

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

5
Senza offesa, ma puzza di cattiva pratica.
ShloEmi,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.