File di dati e di risorse dell'applicazione WPF.
Le applicazioni Microsoft Windows dipendono spesso da file contenenti dati non eseguibili, quali ad esempio Extensible Application Markup Language (XAML), immagini, video e audio. Windows Presentation Foundation (WPF) offre un supporto speciale per la configurazione, l'identificazione e l'utilizzo di questi tipi di file di dati, definiti file di dati dell'applicazione. Questo supporto si basa su un insieme specifico di tipi di file di dati dell'applicazione, tra cui:
File di risorse: file di dati compilati in un assembly WPF eseguibile o di librerie.
File di dati: file di dati autonomi che possiedono un'associazione esplicita a un assembly WPF eseguibile.
File del sito di origine: file di dati autonomi che non possiedono alcuna associazione a un assembly WPF eseguibile.
Un'importante distinzione da fare tra questi tre tipi di file riguarda il fatto che i file di risorse e i file di dati sono resi noti in fase di compilazione, pertanto sono conosciuti esplicitamente da un assembly. Nel caso dei file del sito di origine, invece, è possibile che un assembly non ne abbia alcuna conoscenza oppure che ne abbia una conoscenza implicita tramite un riferimento all'uniform resource identifier (URI) di tipo pack. In quest'ultimo caso, non vi è alcuna garanzia che il file del sito di origine a cui si fa riferimento sia effettivamente esistente.
Per fare riferimento ai file di dati dell'applicazione, Windows Presentation Foundation (WPF) utilizza lo schema uniform resource identifier (URI) di tipo pack, descritto dettagliatamente in URI di tipo pack in WPF.
In questo argomento viene illustrato come configurare e utilizzare i file di dati dell'applicazione.
Nel presente argomento sono contenute le seguenti sezioni.
- File di risorse
- File di dati
- File del sito di origine
- Ricompilazione in seguito a modifica del tipo di compilazione
- Argomenti correlati
File di risorse
Se un file di dati deve sempre essere disponibile per un'applicazione, l'unico modo per garantire la disponibilità è compilarlo nell'assembly eseguibile principale dell'applicazione o in uno degli assembly a cui si fa riferimento. Questo tipo di file di dati dell'applicazione è noto come file di risorse.
I file di risorse devono essere utilizzati nei seguenti casi:
Non occorre aggiornare il contenuto del file di risorse dopo la relativa compilazione in un assembly.
Si desidera semplificare la complessità di distribuzione dell'applicazione riducendo il numero di dipendenze dei file.
Il file di dati dell'applicazione deve essere localizzabile (vedere Cenni preliminari sulla globalizzazione e localizzazione WPF).
Nota |
---|
I dizionari risorse, ossia i file XAML con ResourceDictionary come elemento di primo livello, non sono file di risorse WPF. Mentre i file di risorse WPF possono essere dizionari risorse, un dizionario risorse non deve necessariamente essere un file di risorse (vedere ResourceDictionary). I file di risorse WPF, inoltre, non corrispondono al tipo di risorse incorporato o associato configurabile utilizzando il supporto .NET Framework di base per le risorse di assembly. Vedere Gestione delle risorse delle applicazioni.Mentre i file di risorse WPF sfruttano il supporto per le risorse incorporate .NET Framework di base, l'accesso ai file di risorse WPF mediante URIs di tipo pack risulta più semplice rispetto all'utilizzo degli spazi dei nomi. |
Configurazione dei file di risorse
In WPF, un file di risorse è un file incluso in un progetto Microsoft build engine (MSBuild) come elemento Resource.
<Project "xmlns=https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Resource Include="ResourceFile.xaml" />
</ItemGroup>
...
</Project>
Nota |
---|
Per creare un file di risorse in Microsoft Visual Studio, occorre aggiungere un file a un progetto e impostare Build Action su Resource. |
Quando il progetto viene compilato, MSBuild compila la risorsa nell'assembly.
Utilizzo dei file di risorse
Per caricare un file di risorse è possibile chiamare il metodo GetResourceStream della classe Application, passando un URI di tipo pack che identifica il file di risorse desiderato. GetResourceStream restituisce un oggetto StreamResourceInfo, il quale espone il file di risorse come Stream e ne descrive il tipo di contenuto.
Nel codice di esempio seguente viene illustrato come utilizzare GetResourceStream per caricare un file di risorse Page e impostarlo come contenuto di un oggetto Frame (pageFrame):
' 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
// 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;
Sebbene la chiamata a GetResourceStream consenta di accedere a Stream, è necessario eseguire un'operazione aggiuntiva di conversione nel tipo della proprietà con la quale verrà impostato. In alternativa, è possibile fare in modo che WPF apra e converta Stream caricando un file di risorse direttamente nella proprietà di un tipo tramite codice.
Nell'esempio seguente viene illustrato come caricare Page direttamente in Frame (pageFrame) tramite codice.
Dim pageUri As New Uri("/PageResourceFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("/PageResourceFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Nell'esempio che segue viene illustrato il markup equivalente del precedente esempio.
<Frame Name="pageFrame" Source="PageResourceFile.xaml" />
File di codice dell'applicazione come file di risorse
Tramite URIs di tipo pack è possibile fare riferimento a uno speciale insieme di file di codice dell'applicazione WPF, il quale include finestre, pagine, documenti dinamici e dizionari risorse. Ad esempio, è possibile impostare la proprietà Application.StartupUri con un URI di tipo pack che fa riferimento alla finestra o alla pagina che si desidera caricare all'avvio di un'applicazione.
<Application
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="SOOPage.xaml" />
Questa operazione può essere eseguita quando un file XAML è incluso in un progetto Microsoft build engine (MSBuild) come elemento Page.
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Page Include="MainWindow.xaml" />
</ItemGroup>
...
</Project>
Nota |
---|
In Visual Studio, se si aggiunge un nuovo oggetto Window, NavigationWindow, Page, FlowDocument o ResourceDictionary a un progetto, per impostazione predefinita Build Action per il file di markup viene impostata su Page. |
Quando si compila un progetto con elementi Page, gli elementi XAML vengono convertiti nel formato binario e compilati nell'assembly associato. Di conseguenza, questi file possono essere utilizzati allo stesso modo dei file di risorse tipici.
Nota |
---|
Se un file XAML viene configurato come elemento Resource e non possiede un file code-behind, sarà il codice XAML non elaborato a essere compilato in un assembly e non una versione binaria dello stesso. |
File di dati
Un file di dati viene distribuito come file separato insieme a un assembly eseguibile. Sebbene questi file non vengano compilati in un assembly, dal canto loro gli assembly vengono compilati con i metadati che stabiliscono un'associazione con ciascun file di dati.
È necessario utilizzare i file di dati quando l'applicazione richiede un insieme specifico di file di dati che possono essere aggiornati senza dover ricompilare l'assembly che li utilizza.
Configurazione dei file di dati
Per aggiungere un file di dati a un progetto, è necessario che un file di dati dell'applicazione sia incluso in un elemento Content. Inoltre, dal momento che un file di dati non viene compilato direttamente nell'assembly, è necessario impostare l'elemento di metadati MSBuild CopyToOutputDirectory per specificare che il file di dati viene copiato in un percorso relativo all'assembly compilato. Per fare in modo che la risorsa venga copiata nella cartella dell'output di compilazione ogni qualvolta un progetto viene compilato, impostare l'elemento di metadati CopyToOutputDirectory con il valore Always. In alternativa, è possibile fare in modo che solo la versione più recente della risorsa venga copiata nella cartella dell'output di compilazione utilizzando il valore PreserveNewest.
Di seguito viene illustrato un file configurato come file di dati, il quale viene copiato nella cartella dell'output di compilazione soltanto quando una nuova versione della risorsa viene aggiunta al progetto.
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Content Include="ContentFile.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
...
</Project>
Nota |
---|
Per creare un file di dati in Visual Studio, occorre aggiungere un file a un progetto e impostare Build Action su Content, quindi impostare Copy to Output Directory su Copy always (equivalente a Always) e Copy if newer (equivalente a PreserveNewest). |
Quando il progetto viene compilato, per ogni file di dati viene compilato un attributo AssemblyAssociatedContentFileAttribute nei metadati dell'assembly.
[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]
Il valore di AssemblyAssociatedContentFileAttribute implica il percorso del file di dati relativo alla posizione nel progetto. Ad esempio, se un file di dati si trovasse in una sottocartella del progetto, le informazioni sul percorso aggiuntive verrebbero incorporate nel valore AssemblyAssociatedContentFileAttribute.
[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]
Il valore di AssemblyAssociatedContentFileAttribute è anche il valore del percorso del file di dati nella cartella dell'output di compilazione.
Utilizzo dei file di dati
Per caricare un file di dati è possibile chiamare il metodo GetContentStream della classe Application, passando un URI di tipo pack che identifica il file di dati desiderato. GetContentStream restituisce un oggetto StreamResourceInfo, il quale espone il file di dati come Stream e ne descrive il tipo di contenuto.
Nel codice di esempio seguente viene illustrato come utilizzare GetContentStream per caricare un file di dati Page e impostarlo come contenuto di un oggetto Frame (pageFrame).
' 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
// 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;
Sebbene la chiamata a GetContentStream consenta di accedere a Stream, è necessario eseguire un'operazione aggiuntiva di conversione nel tipo della proprietà con la quale verrà impostato. In alternativa, è possibile fare in modo che WPF apra e converta Stream caricando un file di risorse direttamente nella proprietà di un tipo tramite codice.
Nell'esempio seguente viene illustrato come caricare Page direttamente in Frame (pageFrame) tramite codice.
Dim pageUri As New Uri("/PageContentFile.xaml", UriKind.Relative)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("/PageContentFile.xaml", UriKind.Relative);
this.pageFrame.Source = pageUri;
Nell'esempio che segue viene illustrato il markup equivalente del precedente esempio.
<Frame Name="pageFrame" Source="PageContentFile.xaml" />
File del sito di origine
I file di risorse hanno una relazione esplicita con gli assembly con i quali vengono distribuiti, come definito da AssemblyAssociatedContentFileAttribute. Talvolta, però, è possibile che si debba stabilire una relazione implicita o inesistente tra un assembly e un file di dati dell'applicazione, ad esempio nei seguenti casi:
Un file non esiste in fase di compilazione.
I file richiesti dall'assembly non saranno noti fino alla fase di esecuzione.
Si vuole avere la possibilità di aggiornare i file senza ricompilare l'assembly al quale sono associati.
L'applicazione utilizza file di dati di grandi dimensioni, ad esempio audio e video, che devono essere scaricati dagli utenti unicamente su richiesta.
È possibile caricare questi tipi di file utilizzando schemi URI tradizionali, quali ad esempio gli schemi file:/// e http://.
<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />
Tuttavia, gli schemi file:/// e http:// richiedono che l'applicazione abbia un livello di attendibilità totale. Se l'applicazione è un'XAML browser application (XBAP) avviata da Internet o Intranet e richiede soltanto l'insieme di autorizzazioni consentite per le applicazioni avviate da tali percorsi, i file separati possono essere caricati unicamente dal sito di origine dell'applicazione (percorso di avvio). I file di questo tipo sono noti come file del sito di origine.
I file del sito di origine rappresentano l'unica opzione per le applicazioni parzialmente attendibili, benché non siano limitati a questo tipo di applicazione. È possibile che le applicazioni completamente attendibili debbano caricare file di dati dell'applicazione sconosciuti in fase di compilazione. Sebbene queste applicazioni possano utilizzare file:///, è probabile che i file di dati dell'applicazione vengano installati nella stessa cartella dell'assembly dell'applicazione o in una sottocartella di questo. In questo caso è più facile utilizzare un riferimento al sito di origine piuttosto che file:///, poiché l'utilizzo di file:/// richiede l'elaborazione del percorso completo del file.
Nota |
---|
Al contrario dei file di dati, i file del sito di origine non vengono memorizzati nella cache con un'XAML browser application (XBAP) in un computer client.Di conseguenza vengono scaricati solo se esplicitamente richiesto.Se un'XAML browser application (XBAP) possiede file multimediali di grandi dimensioni, configurandoli come file del sito di origine l'avvio iniziale dell'applicazione sarà molto più rapido e i file verranno scaricati solo su richiesta. |
Configurazione dei file del sito di origine
Se i file del sito di origine sono inesistenti o sconosciuti in fase di compilazione, è necessario utilizzare meccanismi di distribuzione tradizionali per assicurare che i file necessari siano disponibili in fase di esecuzione. Tali meccanismi includono il programma della riga di comando XCopy e Microsoft Windows Installer.
Se in fase di compilazione si conoscono i file da collocare nel sito di origine, ma si vuole comunque evitare una dipendenza esplicita, è possibile aggiungere tali file a un progetto Microsoft build engine (MSBuild) come elemento None. Come per i file di dati, è necessario impostare l'attributo CopyToOutputDirectory MSBuild per specificare che il file del sito di origine viene copiato in un percorso relativo all'assembly compilato, specificando il valore Always o PreserveNewest.
<Project xmlns="https://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<None Include="PageSiteOfOriginFile.xaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
...
</Project>
Nota |
---|
Per creare un file del sito di origine in Visual Studio, occorre aggiungere un file a un progetto e impostare Build Action su None. |
Quando il progetto viene compilato, MSBuild copia i file specificati nella cartella dell'output di 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 URI di tipo pack che identifica il file del sito di origine desiderato. GetRemoteStream restituisce un oggetto StreamResourceInfo, il quale espone il file del sito di origine come Stream e ne descrive il tipo di contenuto.
Nel codice di esempio seguente viene illustrato come utilizzare GetRemoteStream per caricare un file del sito di origine Page e impostarlo come contenuto di un oggetto Frame (pageFrame).
' 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
// 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;
Sebbene la chiamata a GetRemoteStream consenta di accedere a Stream, è necessario eseguire un'operazione aggiuntiva di conversione nel tipo della proprietà con la quale verrà impostato. In alternativa, è possibile fare in modo che WPF apra e converta Stream caricando un file di risorse direttamente nella proprietà di un tipo tramite codice.
Nell'esempio seguente viene illustrato come caricare Page direttamente in Frame (pageFrame) tramite codice.
Dim pageUri As New Uri("pack://siteoforigin:,,,/Subfolder/SiteOfOriginFile.xaml", UriKind.Absolute)
Me.pageFrame.Source = pageUri
Uri pageUri = new Uri("pack://siteoforigin:,,,/SiteOfOriginFile.xaml", UriKind.Absolute);
this.pageFrame.Source = pageUri;
Nell'esempio che segue viene illustrato il markup equivalente del precedente esempio.
<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
Ricompilazione in seguito a modifica del tipo di compilazione
Dopo avere modificato il tipo di compilazione di un file di dati dell'applicazione, è necessario ricompilare l'intera applicazione affinché le modifiche vengano applicate. Se ci si limita a compilare l'applicazione, le modifiche non vengono applicate.