WPF - Usando Resources


A WPF utiliza o termo resource para se referir a dois tipos de coisas distintas:

1 - O primeiro tipo de resource refere-se a itens usados pelo programa que não são criados via código. Isto inclui imagens ou ícones que são fornecidos fora do código e são conhecidos como Assembly Resources.

2- A WPF também usa o termo para descrever código de objetos que são armazenados em um objeto dicionário e então usados em outras partes do código;

As Bibliotecas de classe de uso geral costumam oferecer classes chamadas de dicionários, que você pode usar para armazenar itens que você deseja salvar e recuperar depois. Um dicionário é um recipiente que armazena pares chave-valor, onde o valor é o objeto que você deseja armazenar, e a chave é o objeto que você usa para procurar, depois que ele é armazenado.

Dessa forma a WPF fornece um dicionário de classe chamado ResourceDictionary que é a base de recursos lógicos do WPF.

A classe ResourceDictionary implementa um dicionário para o qual você pode colocar referências a objetos de qualquer tipo, usando chaves de qualquer tipo.

Os objetos são sempre armazenadas como referências do tipo objeto, então depois de recuperá-los do dicionário, você deve lançá-los de volta para seu tipo original.

A classe FrameworkElement tem uma propriedade chamada de Resources do tipo ResourceDictionary e todos os elementos derivados de FrarmeworkElement contém este container pré-embutido. Na figura abaixo temos um esquema da hierarquia da herança onde podemos ver que todos os controles herdam a propriedade Resources .

As setas apontam da classe derivada para classe base.

Neste artigo estamos enfocando o segundo significado e neste caso usar recursos permite que você reutilize código XAML através da definição de valores que você pode usar a partir de muitos lugares em um arquivo XAML.(Não vou entrar em detalhes sobre como usar o ResourceDictionary)

Como os arquivos XAML são gráficos , os resources tendem também a serem gráficos sendo que eles definem objetos e valores que representam propriedades de controles que você pode aplicar a muitos controles com o objetivo de dar uma aparência e comportamento similar.

A criação e utilização de um resource é muito simples e para definir um resource basta incluir a propriedade de um elemento Resources a um objeto como um Grid, Window ou outro container. Dentro deste elemento você inclui os recursos que você irá utilizar posteriormente. Cada recurso é um elemento tal qual um objeto ou um simples valor como um integer ou string.

Ao definir um recurso você deve dar ao mesmo um nome único através do atributo x:Key para identificá-lo.

Para entender melhor vamos a um exemplo prático:

Abra o Visual Basic 2010 Express Edition e crie um novo projeto do tipo WPF Application com o nome wpf_Resources;

A seguir definia no código XAML do arquivo MainWindow.xaml o recurso conforme a seguir:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Usando Resources" Height="350" Width="525">
    <Window.Resources>
        <LinearGradientBrush x:Key="brButton" StartPoint="0,0" EndPoint="0,1">
            <GradientStop Color="Yellow" Offset="0"/>
            <GradientStop Color="White" Offset="0.5"/>
            <GradientStop Color="Blue" Offset="1"/>
        </LinearGradientBrush>
        <BitmapEffectGroup x:Key="bmeButton">
            <DropShadowBitmapEffect/>
        </BitmapEffectGroup>
    </Window.Resources>
    <Grid>
     </Grid>
</Window>

O código acima define um elemento Resources que contém um RadialGradientBrush chamado brButton e um BitmapEffectGroup chamado bmeButton.

Este elemento Resources esta contido no elemento Window do arquivo: <Window.Resources>

Qualquer objeto contido no objeto que trata o elemento Resources pode usar o recurso. No exemplo acima Window contém o elemento Resources de forma que qualquer objeto em Window pode usar o recurso.

Após definir uma simples propriedade de recurso tal como fizemos, podemos usá-lo. O valor que você dá ao atributo deverá ter o formato {StaticResource nome_recurso}, onde você coloca em nome_recurso o nome do recurso definido.

Para usar o recurso definido vamos definir no código XAML um Button e definir sua propriedade BackGround para o recurso brButton e a sua propriedade BitMapEffect para o recurso bmeButton conforme abaixo:

O resultado pode ser visto na janela do descritor WPF onde vemos o button usando o recurso definido.

StaticResource e DynamicResource

Quando você atribui uma referência de recurso a uma propriedade ele pode ser atribuído tanto como um StaticResource ou como um DynamicResource.

Apesar da nomenclatura, não são os próprios recursos que são estáticos ou dinâmicos, o mesmo recurso pode ser usado como um StaticResource quando atribuído a uma propriedade e como DynamicResource quando atribuído a outra. A diferença está em saber se a referência no ResourceDictionary é acompanhada por mudanças, que são então repassadas para a referenciação de propriedade do recurso.

Vejamos um exemplo prático para mostrar essa característica.

Inclua uma nova janela Window1.xaml no projeto wpf_Resources e a seguir defina o seguinte código XAML no arquivo Window1.xaml:

<Window x:Class="Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300">
    <Window.Resources>
        <LinearGradientBrush x:Key="gradBrush" StartPoint="0,0" EndPoint="1,1">
            <GradientStop Color="Yellow" Offset="0" />
            <GradientStop Color="BurlyWood" Offset="1"/>
        </LinearGradientBrush>
    </Window.Resources>
    <Grid>
        <StackPanel Background="{DynamicResource gradBrush}" Name="sp">
            <TextBlock FontFamily="Arial Black" Margin="7" Background="{DynamicResource gradBrush}"> <- Buttons - DynamicResource </TextBlock>
            <Button Height="40" Name="btn1" FontWeight="Bold" Background="{StaticResource gradBrush}"> <-  Button 1 - StaticResource </Button>
            <Button Height="40" Name="btn2" FontWeight="Bold" Background="{DynamicResource gradBrush}"> <- Button 2 - DynamicResource </Button>
            <Button HorizontalAlignment="Right" Click="Button_Click">Alterar</Button>
        </StackPanel>
    </Grid>
</Window>

No código acima temos um botão usando o recurso como StaticResource e outro como DynamicResource.

A seguir vamos inclui o code-behind no arquivo Window1.xaml.vb referente ao evento Click do botão - Alterar:

 Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
        Me.Resources("gradBrush") = Brushes.HotPink
    End Sub

Este código esta alterando o recurso gradBrush.

Executando o projeto teremos o seguinte resultado:

===>
Janela inicial   Depois de alterar a propriedade

Observe que o botão referenciado como StaticResource :

<Button Height="40" Name="btn1" FontWeight="Bold" Background="{StaticResource gradBrush}">

Não sofreu alteração.

Para definir um DynamicResource no code-behind devemos usar o método SetResourceReference com a seguinte sintaxe:

btn2.SetResourceReference(BackgroundProperty, "gradBrush" );

Assim temos um visão geral sobre os conceitos e propriedades de Resources da WPF.

Pegue o projeto completo aqui: wpf_Resources.zip

"E a ninguém na terra chameis vosso pai, porque um só é o vosso Pai, o qual esta nos céus."
"Nem vos chameis mestres, porque um só é o vosso Mestre, que é o Cristo." Mateus 23:9-10

Referências:


José Carlos Macoratti