Recursos, conteúdo e arquivos de dados do aplicativo WPF
Os aplicativos do Microsoft Windows geralmente dependem de arquivos que contêm dados não executáveis, como XAML (Extensible Application Markup Language), imagens, vídeo e áudio. O WPF (Windows Presentation Foundation) oferece suporte especial para configurar, identificar e usar esses tipos de arquivos de dados, que são chamados de arquivos de dados do aplicativo. Esse suporte gira em torno de um conjunto específico de tipos de arquivo de dados de aplicativo, incluindo:
Arquivos de Recursos: arquivos de dados compilados em um assembly WPF, seja um executável ou uma biblioteca.
Arquivos de Conteúdo: arquivos de dados independentes que têm uma associação explícita com um assembly do WPF executável.
Site de Arquivos de Origem: arquivos de dados autônomos que não têm associação com um assembly WPF executável.
Uma distinção importante a fazer entre esses três tipos de arquivos é que arquivos de recurso e arquivos de conteúdo são conhecidos no momento da compilação; um assembly tem conhecimento explícito deles. Para arquivos de site de origem, no entanto, um assembly pode não ter nenhum conhecimento sobre eles ou ter um conhecimento implícito por meio de uma referência de URI (Uniform Resource Identifier) "pack://" e, nesse último caso, não há nenhuma garantia de que o local referenciado do arquivo de origem realmente existe.
Para fazer referência aos arquivos de dados do aplicativo, o Windows Presentation Foundation (WPF) utiliza o esquema Pack Uniform Resource Identifier (URI), que é descrito em detalhes em Pack URIs no WPF).
Este tópico descreve como configurar e usar arquivos de dados do aplicativo.
Arquivos de recurso
Se um arquivo de dados do aplicativo precisar estar sempre disponível para um aplicativo, a única maneira de garantir essa disponibilidade será compilá-lo em um assembly executável principal do aplicativo ou em um de seus assemblies referenciados. Esse tipo de arquivo de dados do aplicativo é conhecido como um arquivo de recurso .
Você deve usar arquivos de recurso quando:
Você não precisa atualizar o conteúdo do arquivo de recurso depois que ele é compilado em um assembly.
Você deseja simplificar a complexidade da distribuição de aplicativos reduzindo o número de dependências de arquivo.
O arquivo de dados do aplicativo precisa ser localizável (consulte visão geral de globalização e localização do WPF).
Nota
Os arquivos de recurso descritos nesta seção são diferentes dos arquivos de recurso descritos em recursos XAML e diferentes dos recursos inseridos ou vinculados descritos em Gerenciar Recursos de Aplicativo (.NET).
Configurando arquivos de recurso
No WPF, um arquivo de recurso é um arquivo incluído em um projeto do MSBuild (mecanismo de build da Microsoft) como um item de Resource
.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Resource Include="ResourceFile.xaml" />
</ItemGroup>
...
</Project>
Nota
No Visual Studio, você cria um arquivo de recurso adicionando um arquivo a um projeto e definindo seu Build Action
para Resource
.
Quando o projeto é criado, o MSBuild compila o recurso no assembly.
Usando arquivos de recurso
Para carregar um arquivo de recurso, você pode chamar o método GetResourceStream da classe Application, passando um URI de pacote que identifica o arquivo de recurso desejado. GetResourceStream retorna um objeto StreamResourceInfo, que expõe o arquivo de recurso como um Stream e descreve seu tipo de conteúdo.
Como exemplo, o código a seguir mostra como usar GetResourceStream para carregar um arquivo de recurso Page e defini-lo como o conteúdo de um 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
Ao chamar GetResourceStream, você obtém acesso ao Stream, mas é necessário realizar o trabalho adicional de convertê-lo para o tipo da propriedade com a qual ele será definido. Em vez disso, você pode permitir que o WPF cuide de abrir e converter o Stream ao carregar um arquivo de recurso diretamente em uma propriedade de um tipo usando código.
O exemplo a seguir mostra como carregar um Page diretamente em um Frame (pageFrame
) usando código.
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
O exemplo a seguir é o equivalente em marcação em código do exemplo anterior.
<Frame Name="pageFrame" Source="PageResourceFile.xaml" />
Arquivos de código do aplicativo como arquivos de recurso
Um conjunto especial de arquivos de código do aplicativo WPF pode ser referenciado usando URIs de pacote, incluindo janelas, páginas, documentos de fluxo e dicionários de recursos. Por exemplo, você pode definir a propriedade Application.StartupUri com um URI de pacote que faz referência à janela ou página que deseja carregar quando um aplicativo é iniciado.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="SOOPage.xaml" />
Você pode fazer isso quando um arquivo XAML é incluído em um projeto do MSBuild como um item de Page
.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Page Include="MainWindow.xaml" />
</ItemGroup>
...
</Project>
Nota
No Visual Studio, você adiciona um novo Window, NavigationWindow, Page, FlowDocumentou ResourceDictionary a um projeto, o Build Action
do arquivo de marcação terá como padrão Page
.
Quando um projeto com itens Page
é compilado, os itens XAML são convertidos em formato binário e compilados no assembly associado. Consequentemente, esses arquivos podem ser usados da mesma forma que os arquivos de recursos típicos.
Nota
Se um arquivo XAML estiver configurado como um item de Resource
e não tiver um arquivo de código subjacente, o XAML bruto será compilado em um assembly em vez de uma versão binária do XAML bruto.
Arquivos de conteúdo
Um arquivo de conteúdo é distribuído como um arquivo independente ao lado de uma assemblagem executável. Embora eles não sejam compilados em um assembly, os assemblies são compilados com metadados que estabelecem uma associação com cada arquivo de conteúdo.
Você deve usar arquivos de conteúdo quando o aplicativo requer um conjunto específico de arquivos de dados do aplicativo que você deseja ser capaz de atualizar sem recompilar o assembly que os consome.
Configurando arquivos de conteúdo
Para adicionar um arquivo de conteúdo a um projeto, um arquivo de dados do aplicativo deve ser incluído como um item de Content
. Além disso, como um arquivo de conteúdo não é compilado diretamente no assembly, você precisa definir o elemento de metadados do MSBuild CopyToOutputDirectory
para especificar que o arquivo de conteúdo seja copiado para um local relativo ao assembly compilado. Se você quiser que o recurso seja copiado para a pasta de saída de build sempre que um projeto for criado, defina o elemento de metadados CopyToOutputDirectory
com o valor Always
. Caso contrário, você poderá garantir que apenas a versão mais recente do recurso seja copiada para a pasta de saída de build usando o valor PreserveNewest
.
O seguinte mostra um arquivo configurado como um arquivo de conteúdo que é copiado para a pasta de saída de build somente quando uma nova versão do recurso é adicionada ao projeto.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<ItemGroup>
<Content Include="ContentFile.xaml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
...
</Project>
Nota
No Visual Studio, você cria um arquivo de conteúdo adicionando um arquivo a um projeto e definindo seu Build Action
como Content
e definindo seu Copy to Output Directory
como Copy always
(o mesmo que Always
) e Copy if newer
(o mesmo que PreserveNewest
).
Quando o projeto é criado, um atributo AssemblyAssociatedContentFileAttribute é compilado nos metadados do assembly para cada arquivo de conteúdo.
[assembly: AssemblyAssociatedContentFile("ContentFile.xaml")]
O valor da AssemblyAssociatedContentFileAttribute indica o caminho do arquivo de conteúdo em relação à sua posição no projeto. Por exemplo, se um arquivo de conteúdo estiver localizado em uma subpasta de projeto, as informações de caminho adicionais serão incorporadas ao valor AssemblyAssociatedContentFileAttribute.
[assembly: AssemblyAssociatedContentFile("Resources/ContentFile.xaml")]
O valor AssemblyAssociatedContentFileAttribute também é o valor do caminho para o arquivo de conteúdo na pasta de saída de build.
Usando Arquivos de Conteúdo
Para carregar um arquivo de conteúdo, você pode chamar o método GetContentStream da classe Application, passando um URI de pacote que identifica o arquivo de conteúdo desejado. GetContentStream retorna um objeto StreamResourceInfo, que expõe o arquivo de conteúdo como um Stream e descreve seu tipo de conteúdo.
Por exemplo, o código a seguir mostra como usar GetContentStream para carregar um arquivo de conteúdo Page e defini-lo como o conteúdo de um 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
Ao chamar GetContentStream, você obtém acesso ao Stream, mas é necessário realizar o trabalho adicional de convertê-lo para o tipo da propriedade com a qual ele será definido. Em vez disso, você pode permitir que o WPF cuide de abrir e converter o Stream ao carregar um arquivo de recurso diretamente em uma propriedade de um tipo usando código.
O exemplo a seguir mostra como carregar um Page diretamente em um Frame (pageFrame
) usando código.
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
O exemplo a seguir é o equivalente em marcação do exemplo anterior.
<Frame Name="pageFrame" Source="PageContentFile.xaml" />
Arquivos de site de origem
Os arquivos de recurso têm um relacionamento explícito com os assemblies que são distribuídos junto com eles, de acordo com a definição do AssemblyAssociatedContentFileAttribute. Porém, há momentos em que talvez você queira estabelecer uma relação implícita ou inexistente entre um assembly e um arquivo de dados do aplicativo, incluindo quando:
Um arquivo não existe no momento da compilação.
Você não sabe quais arquivos seu assembly exigirá até o momento da execução.
Você deseja poder atualizar arquivos sem a necessidade de recompilação do assembly ao qual eles estão associados.
Seu aplicativo usa arquivos de dados grandes, como áudio e vídeo, e você só deseja que os usuários os baixem se quiserem.
É possível carregar esses tipos de arquivos usando esquemas de URI tradicionais, como os esquemas file:///
e http://
.
<Image Source="file:///C:/DataFile.bmp" />
<Image Source="http://www.datafilewebsite.com/DataFile.bmp" />
No entanto, os esquemas file:///
e http://
exigem que seu aplicativo tenha total confiança. Se o aplicativo for um XBAP (aplicativo do navegador XAML) que foi iniciado da Internet ou da intranet e solicitará apenas o conjunto de permissões permitidas para aplicativos iniciados desses locais, arquivos soltos só poderão ser carregados do site de origem do aplicativo (local de inicialização). Esses arquivos são conhecidos como arquivos de site de origem.
Os arquivos de site de origem são a única opção para aplicativos de confiança parcial, embora não estejam limitados a aplicativos de confiança parcial. Aplicativos de confiança total poderão ainda precisar carregar arquivos de dados do aplicativo que não são conhecidos no tempo de compilação; embora possam usar file:///, é provável que os arquivos de dados do aplicativo sejam instalados na mesma pasta ou em uma subpasta do assembly do aplicativo. Nesse caso, usar a referência de site de origem é mais fácil do que usar file:///, pois usar file:/// exige que você trabalhe o caminho completo do arquivo.
Nota
Os arquivos de site de origem não são armazenados em cache com um XBAP (aplicativo do navegador XAML) em um computador cliente, mas os arquivos de conteúdo são. Consequentemente, eles só são baixados quando solicitados especificamente. Se um aplicativo XBAP (aplicativo do navegador XAML) tiver arquivos de mídia grandes, configurá-los como arquivos de site de origem significa que o início inicial do aplicativo é muito mais rápido e os arquivos são baixados apenas sob demanda.
Configurando arquivos de site de origem
Se os arquivos de site de origem forem inexistentes ou desconhecidos no momento da compilação, você precisará usar mecanismos de implantação tradicionais para garantir que os arquivos necessários estejam disponíveis em tempo de execução, incluindo o uso do programa de linha de comando XCopy
ou do Microsoft Windows Installer.
Se você souber em tempo de compilação os arquivos que deseja localizar no site de origem, mas ainda quiser evitar uma dependência explícita, poderá adicionar esses arquivos a um projeto do MSBuild como None
item. Assim como acontece com os arquivos de conteúdo, você precisa definir o atributo CopyToOutputDirectory
MSBuild para especificar que o arquivo de site de origem seja copiado para um local relativo ao assembly compilado, especificando o valor Always
ou o valor PreserveNewest
.
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ... >
...
<None Include="PageSiteOfOriginFile.xaml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
...
</Project>
Nota
No Visual Studio, você cria um arquivo de site de origem adicionando um arquivo a um projeto e definindo seu Build Action
para None
.
Quando o projeto é criado, o MSBuild copia os arquivos especificados para a pasta de saída de build.
Usando arquivos de site de origem
Para carregar um arquivo de site de origem, você pode chamar o método GetRemoteStream da classe Application, passando um URI de pacote que identifica o site desejado do arquivo de origem. GetRemoteStream retorna um objeto StreamResourceInfo, que expõe o site do arquivo de origem como um Stream e descreve seu tipo de conteúdo.
Como exemplo, o código a seguir mostra como usar GetRemoteStream para carregar um arquivo de site de origem Page e defini-lo como o conteúdo de um 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
Ao chamar GetRemoteStream, você obtém acesso ao Stream, mas é necessário realizar o trabalho adicional de convertê-lo para o tipo da propriedade com a qual ele será definido. Em vez disso, você pode permitir que o WPF cuide de abrir e converter o Stream ao carregar um arquivo de recurso diretamente em uma propriedade de um tipo usando código.
O exemplo a seguir mostra como carregar um Page diretamente em um Frame (pageFrame
) usando código.
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
O exemplo a seguir é um exemplo de marcação equivalente ao anterior.
<Frame Name="pageFrame" Source="pack://siteoforigin:,,,/SiteOfOriginFile.xaml" />
Reconstrução após alterar o tipo de construção
Depois de alterar o tipo de build de um arquivo de dados do aplicativo, você precisará recompilar todo o aplicativo para garantir que essas alterações sejam aplicadas. Se você compilar apenas o aplicativo, as alterações não serão aplicadas.
Consulte também
.NET Desktop feedback