Condividi tramite


Risorse dell'applicazione WPF, file di contenuto e di dati

Le applicazioni Microsoft Windows spesso dipendono da file che contengono dati non eseguibili, ad esempio XAML (Extensible Application Markup Language), immagini, video e audio. Windows Presentation Foundation (WPF) offre un supporto speciale per la configurazione, l'identificazione e l'uso di questi tipi di file di dati, denominati file di dati dell'applicazione. Questo supporto si basa su un set specifico di tipi di file di dati dell'applicazione, tra cui:

  • File Risorse: File dati che sono compilati in un assembly WPF eseguibile o di libreria.

  • File di Contenuto: file autonomi che hanno un'associazione esplicita a un assembly WPF eseguibile.

  • File di origine del sito: file di dati autonomi che non hanno alcuna associazione a un assembly WPF eseguibile.

Una distinzione importante da fare tra questi tre tipi di file è che i file di risorse e i file di contenuto sono noti in fase di compilazione; un assembly ha una conoscenza esplicita di tali file. Per i file del sito di origine, tuttavia, un assembly potrebbe non avere alcuna conoscenza di essi, o una conoscenza implicita tramite un riferimento URI pack (Uniform Resource Identifier); nel caso di quest'ultimo, non vi è alcuna garanzia che il file del sito di origine di riferimento esista effettivamente.

Per fare riferimento ai file di dati dell'applicazione, Windows Presentation Foundation (WPF) usa lo schema URI (Uniform Resource Identifier) Pack, descritto in dettaglio in Pack URIs in WPF).

In questo argomento viene descritto come configurare e usare i file di dati dell'applicazione.

File di risorse

Se un file di dati dell'applicazione deve essere sempre disponibile per un'applicazione, l'unico modo per garantire la disponibilità consiste nel compilarlo nell'assembly eseguibile principale di un'applicazione o in uno degli assembly a cui si fa riferimento. Questo tipo di file di dati dell'applicazione è noto come file di risorse .

È consigliabile usare i file di risorse quando:

  • Non è necessario aggiornare il contenuto del file di risorse dopo la compilazione in un assembly.

  • Si vuole semplificare la complessità della distribuzione delle applicazioni riducendo il numero di dipendenze dei file.

  • Il file di dati dell'applicazione deve essere localizzabile (vedere Cenni preliminari sulla globalizzazione e la localizzazione WPF).

Nota

I file di risorse descritti in questa sezione sono diversi dai file di risorse descritti in risorse XAML e diverse dalle risorse incorporate o collegate descritte in Gestire le risorse dell'applicazione (.NET).

Configurazione dei file di risorse

In WPF un file di risorse è un file incluso in un progetto del motore di compilazione Microsoft (MSBuild) come elemento Resource.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Resource Include="ResourceFile.xaml" />  
  </ItemGroup>  
  ...  
</Project>  

Nota

In Visual Studio si crea un file di risorse aggiungendo un file a un progetto e impostandone il Build Action su Resource.

Quando il progetto viene compilato, MSBuild compila la risorsa nell'assembly.

Uso di file di risorse

Per caricare un file di risorse, è possibile chiamare il metodo GetResourceStream della classe Application, passando un URI pack che identifica il file di risorse desiderato. GetResourceStream restituisce un oggetto StreamResourceInfo, che espone il file di risorse come Stream e ne descrive il tipo di contenuto.

Ad esempio, il codice seguente illustra come usare GetResourceStream per caricare un file di risorse Page e impostarlo come contenuto di un Frame (pageFrame):

// Navigate to xaml page
Uri uri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetResourceStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetResourceStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

Chiamando GetResourceStream, si accede a Stream, ma è necessario eseguire il lavoro aggiuntivo di conversione al tipo della proprietà con cui verrà impostato. È invece possibile consentire a WPF di aprire e convertire il Stream caricando un file di risorse direttamente nella proprietà di un tipo usando il codice.

Nell'esempio seguente viene illustrato come caricare un Page direttamente in un Frame (pageFrame) usando il codice .

Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri

L'esempio seguente è l'equivalente di markup dell'esempio precedente.

<Frame Name="pageFrame" Source="PageResourceFile.xaml" />

File di codice dell'applicazione come file di risorse

È possibile fare riferimento a un set speciale di file di codice dell'applicazione WPF usando gli URI pack, tra cui finestre, pagine, documenti di flusso e dizionari risorse. Ad esempio, è possibile impostare la proprietà Application.StartupUri con un URI pack che fa riferimento alla finestra o alla pagina da caricare all'avvio di un'applicazione.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="SOOPage.xaml" />

Puoi farlo quando un file XAML è incluso in un progetto MSBuild come elemento Page.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Page Include="MainWindow.xaml" />  
  </ItemGroup>  
  ...  
</Project>  

Nota

In Visual Studio si aggiunge un nuovo Window, NavigationWindow, Page, FlowDocumento ResourceDictionary a un progetto, per impostazione predefinita il Build Action per il file di markup verrà Page.

Quando un progetto con Page elementi viene compilato, gli elementi XAML vengono convertiti in formato binario e compilati nell'assembly associato. Di conseguenza, questi file possono essere usati nello stesso modo dei file di risorse tipici.

Nota

Se un file XAML è configurato come elemento Resource e non dispone di un file code-behind, il codice XAML non elaborato viene compilato in un assembly anziché in una versione binaria del codice XAML non elaborato.

File di contenuto

Un file di contenuto viene distribuito come file libero insieme a un assembly eseguibile. Anche se non vengono compilati all'interno di un assembly, gli assembly stessi vengono compilati con metadati che stabiliscono un'associazione con ogni file di contenuto.

È consigliabile usare i file di contenuto quando l'applicazione richiede un set specifico di file di dati dell'applicazione che si desidera aggiornare senza ricompilare l'assembly che li utilizza.

Configurazione dei file di contenuto

Per aggiungere un file di contenuto a un progetto, è necessario includere un file di dati dell'applicazione come elemento Content. Inoltre, poiché un file di contenuto non viene compilato direttamente nell'assembly, è necessario impostare MSBuild CopyToOutputDirectory elemento di metadati per specificare che il file di contenuto viene copiato in un percorso relativo all'assembly compilato. Vuoi copiare la risorsa nella cartella di output di compilazione ogni volta che viene compilato un progetto? Imposta l'elemento di metadati CopyToOutputDirectory con il valore Always. In caso contrario, è possibile assicurarsi che solo la versione più recente della risorsa venga copiata nella cartella di output di compilazione usando il valore PreserveNewest.

Di seguito viene illustrato un file configurato come file di contenuto copiato nella cartella di output della compilazione solo quando viene aggiunta una nuova versione della risorsa al progetto.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <ItemGroup>  
    <Content Include="ContentFile.xaml">  
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>  
    </Content>  
  </ItemGroup>  
  ...  
</Project>  

Nota

In Visual Studio si crea un file di contenuto aggiungendo un file a un progetto e impostandone il Build Action su Contente impostandone il Copy to Output Directory su Copy always (uguale a Always) e Copy if newer (uguale a PreserveNewest).

Quando il progetto viene compilato, un attributo AssemblyAssociatedContentFileAttribute viene compilato nei metadati dell'assembly per ogni file di contenuto.

[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]

Il valore del AssemblyAssociatedContentFileAttribute implica il percorso del file di contenuto rispetto alla relativa posizione nel progetto. Ad esempio, se un file di contenuto si trova in una sottocartella di progetto, le informazioni aggiuntive sul percorso verranno incorporate nel valore AssemblyAssociatedContentFileAttribute.

[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]

Il valore AssemblyAssociatedContentFileAttribute è anche il valore del percorso del file di contenuto nella cartella di output di compilazione.

Uso dei file di contenuto

Per caricare un file di contenuto, è possibile chiamare il metodo GetContentStream della classe Application, passando un URI di pacchetto che identifica il file di contenuto desiderato. GetContentStream restituisce un oggetto StreamResourceInfo, che espone il file di contenuto come Stream e ne descrive il tipo di contenuto.

Ad esempio, il codice seguente illustra come usare GetContentStream per caricare un file di contenuto Page e impostarlo come contenuto di un Frame (pageFrame).

// Navigate to xaml page
Uri uri = new Uri("/PageContentFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetContentStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetContentStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

Sebbene la chiamata GetContentStream dia accesso alla Stream, è necessario svolgere il lavoro aggiuntivo di convertirla nel tipo di proprietà che verrà impostata. È invece possibile consentire a WPF di aprire e convertire il Stream caricando un file di risorse direttamente nella proprietà di un tipo usando il codice.

Nell'esempio seguente viene illustrato come caricare un Page direttamente in un Frame (pageFrame) usando il codice .

Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri

L'esempio seguente è l'equivalente markup dell'esempio precedente.

<Frame Name="pageFrame" Source="PageContentFile.xaml" />

File del sito di origine

I file di risorse hanno una relazione esplicita con gli assembly con cui sono distribuiti, come definito dal AssemblyAssociatedContentFileAttribute. In alcuni casi, tuttavia, è possibile stabilire una relazione implicita o inesistente tra un assembly e un file di dati dell'applicazione, tra cui quando:

  • Un file non esiste in fase di compilazione.

  • Non si conoscono i file necessari per l'assemblaggio fino al tempo di esecuzione.

  • Si vuole essere in grado di aggiornare i file senza ricompilare l'assembly a cui sono associati.

  • L'applicazione usa file di dati di grandi dimensioni, ad esempio audio e video, e si vuole che gli utenti li scarichino solo se scelgono di.

È possibile caricare questi tipi di file usando schemi URI tradizionali, ad esempio gli schemi file:/// e http://.

<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />

Tuttavia, gli schemi di file:/// e http:// richiedono che l'applicazione disponga dell'attendibilità totale. Se l'applicazione è un'applicazione browser XAML (XBAP) avviata da Internet o Intranet e richiede solo il set di autorizzazioni consentite per le applicazioni avviate da tali posizioni, i file separati possono essere caricati solo dal sito di origine dell'applicazione (posizione di avvio). Questi file sono noti come file del sito di origine.

I file del sito di origine sono l'unica opzione per le applicazioni parzialmente attendibili, anche se non sono limitate alle applicazioni parzialmente attendibili. Le applicazioni con attendibilità completa potrebbero comunque dover caricare i file di dati dell'applicazione che non conoscono in fase di compilazione; sebbene le applicazioni con attendibilità completa possano usare file:///, è probabile che i file di dati dell'applicazione vengano installati nella stessa cartella di o una sottocartella dell'assembly dell'applicazione. In questo caso, l'uso del riferimento al sito di origine è più semplice rispetto all'uso di file:///, perché l'uso di file:/// richiede di elaborare il percorso completo del file.

Nota

I file del sito di origine non vengono memorizzati nella cache dai browser delle applicazioni XAML (XBAP) su un computer del cliente, mentre i file di contenuto sì. Di conseguenza, vengono scaricati solo quando richiesto specificamente. Se un'applicazione browser XAML (XBAP) include file multimediali di grandi dimensioni, configurarli come file di origine significa che l'avvio iniziale dell'applicazione è molto più veloce e i file vengono scaricati solo su richiesta.

Configurazione dei file del sito di origine

Se il sito dei file di origine non è esistente o sconosciuto in fase di compilazione, è necessario usare i meccanismi di distribuzione tradizionali per garantire che i file necessari siano disponibili in fase di esecuzione, incluso l'uso del programma da riga di comando XCopy o di Microsoft Windows Installer.

Se si conosce in fase di compilazione i file da individuare nel sito di origine, ma si vuole comunque evitare una dipendenza esplicita, è possibile aggiungere tali file a un progetto MSBuild come elemento None. Come per i file di contenuto, è necessario impostare l'attributo msbuild CopyToOutputDirectory per specificare che il file del sito di origine viene copiato in un percorso relativo all'assembly compilato, specificando il valore Always o il valore PreserveNewest.

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >  
  ...  
  <None Include="PageSiteOfOriginFile.xaml">  
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>  
  </None>  
  ...  
</Project>  

Nota

In Visual Studio si crea un file del sito di origine aggiungendo un file a un progetto e impostandone il Build Action su None.

Quando il progetto viene compilato, MSBuild copia i file specificati nella cartella di output della compilazione.

Utilizzo dei file del sito di origine

Per caricare un file del sito di origine, è possibile chiamare il metodo GetRemoteStream della classe Application, passando un pack URI che identifica il file desiderato del sito di origine. GetRemoteStream restituisce un oggetto StreamResourceInfo, che espone il file del sito di origine come Stream e ne descrive il tipo di contenuto.

Ad esempio, il codice seguente illustra come usare GetRemoteStream per caricare un file di origine del sito Page e impostarlo come contenuto di un Frame (pageFrame).

// Navigate to xaml page
Uri uri = new Uri("/SiteOfOriginFile.xaml", UriKind.Relative);
StreamResourceInfo info = Application.GetRemoteStream(uri);
System.Windows.Markup.XamlReader reader = new System.Windows.Markup.XamlReader();
Page page = (Page)reader.LoadAsync(info.Stream);
this.pageFrame.Content = page;
' Navigate to xaml page
Dim uri As New Uri("/SiteOfOriginFile.xaml", UriKind.Relative)
Dim info As StreamResourceInfo = Application.GetRemoteStream(uri)
Dim reader As New System.Windows.Markup.XamlReader()
Dim page As Page = CType(reader.LoadAsync(info.Stream), Page)
Me.pageFrame.Content = page

Chiamare GetRemoteStream consente di accedere a Stream, ma è necessario eseguire il lavoro aggiuntivo di convertirlo nel tipo della proprietà con cui verrà impostato. È invece possibile consentire a WPF di aprire e convertire il Stream caricando un file di risorse direttamente nella proprietà di un tipo usando il codice.

Nell'esempio seguente viene illustrato come caricare un Page direttamente in un Frame (pageFrame) usando il codice .

Uri pageUri = new Uri("pack://siteoforigin:,,,/SiteOfOriginFile.xaml", UriKind.Absolute);
this.pageFrame.Source = pageUri;
Dim pageUri As New Uri("pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml", UriKind.Absolute)
Me.pageFrame.Source = pageUri

L'esempio seguente è l'equivalente in linguaggio di markup dell'esempio precedente.

<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />

Ricostruzione dopo la modifica del tipo di build

Dopo aver modificato il tipo di compilazione di un file di dati dell'applicazione, è necessario ricompilare l'intera applicazione per assicurarsi che tali modifiche vengano applicate. Se si compila solo l'applicazione, le modifiche non vengono applicate.

Vedere anche