Partilhar via


Visão geral do XAML

Este artigo descreve os recursos da linguagem XAML e demonstra como você pode usar XAML para escrever aplicativos do Windows Presentation Foundation (WPF). Este artigo descreve especificamente o XAML conforme implementado pelo WPF. O próprio XAML é um conceito de linguagem maior do que o WPF.

O que é XAML

XAML é uma linguagem de marcação declarativa. Conforme aplicado ao modelo de programação .NET, o XAML simplifica a criação de uma interface do usuário para um aplicativo .NET. Você pode criar elementos visíveis da interface do usuário na marcação XAML declarativa e, em seguida, separar a definição da interface do usuário da lógica de tempo de execução usando arquivos code-behind que são unidos à marcação por meio de definições de classe parciais. XAML representa diretamente a instanciação de objetos em um conjunto específico de tipos de suporte definidos em assemblies. Isso é diferente da maioria das outras linguagens de marcação, que normalmente são uma linguagem de interpretação sem uma ligação direta a um sistema de tipos subjacente. O XAML permite um fluxo de trabalho onde partes separadas podem trabalhar na interface do usuário e na lógica de um aplicativo, usando ferramentas potencialmente diferentes.

Quando representados como texto, os arquivos XAML são arquivos XML que geralmente têm a .xaml extensão. Os arquivos podem ser codificados por qualquer codificação XML, mas a codificação como UTF-8 é típica.

O exemplo a seguir mostra como você pode criar um botão como parte de uma interface do usuário. Este exemplo destina-se a dar a você uma ideia de como o XAML representa metáforas comuns de programação da interface do usuário (não é um exemplo completo).

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Sintaxe XAML em resumo

As seções a seguir explicam as formas básicas da sintaxe XAML e dão um pequeno exemplo de marcação. Essas seções não se destinam a fornecer informações completas sobre cada forma de sintaxe, como como elas são representadas no sistema de tipo de suporte. Para obter mais informações sobre as especificidades da sintaxe XAML, consulte Sintaxe XAML em detalhes.

Grande parte do material nas próximas seções será elementar para você se você tiver familiaridade anterior com a linguagem XML. Isso é uma consequência de um dos princípios básicos de design do XAML. A linguagem XAML define conceitos próprios, mas esses conceitos funcionam dentro da linguagem XML e do formulário de marcação.

Elementos de objeto XAML

Um elemento objeto declara normalmente uma instância de um tipo. Esse tipo é definido nos assemblys referenciados pela tecnologia que utiliza XAML como linguagem.

A sintaxe do elemento objeto sempre começa com um colchete angular de abertura (<). Isso é seguido pelo nome do tipo onde você deseja criar uma instância. (O nome pode incluir um prefixo, um conceito que será explicado mais tarde.) Depois disso, você pode, opcionalmente, declarar atributos no elemento object. Para completar o tag do elemento objeto, termine com um parêntesis angular de fechamento (>). Em vez disso, você pode usar um formulário de fechamento automático que não tenha conteúdo, preenchendo a tag com uma barra e colchete angular de fechamento sucessivamente (/>). Por exemplo, observe novamente o trecho de marcação mostrado anteriormente.

<StackPanel>
    <Button Content="Click Me"/>
</StackPanel>

Isso especifica dois elementos de objeto: <StackPanel> (com conteúdo e uma tag de fechamento mais tarde) e <Button .../> (o formulário de fechamento automático, com vários atributos). Os elementos de objeto StackPanel e Button mapeiam para o nome de uma classe definida pelo WPF e que faz parte das bibliotecas do WPF. Ao especificar uma marca de elemento de objeto, você cria uma instrução para processamento XAML para criar uma nova instância do tipo subjacente. Cada instância é criada chamando o construtor sem parâmetros do tipo subjacente ao analisar e carregar o XAML.

Sintaxe do atributo (propriedades)

As propriedades de um objeto geralmente podem ser expressas como atributos do elemento object. A sintaxe do atributo nomeia a propriedade do objeto que está sendo definida, seguida pelo operador de atribuição (=). O valor de um atributo é sempre especificado como uma cadeia de caracteres contida entre aspas.

A sintaxe de atributo é a sintaxe de configuração de propriedade mais simplificada e é a sintaxe mais intuitiva a ser usada por desenvolvedores que usaram linguagens de marcação no passado. Por exemplo, a marcação a seguir cria um botão com texto vermelho e um plano de fundo azul com um texto de exibição de Content.

<Button Background="Blue" Foreground="Red" Content="This is a button"/>

Sintaxe do elemento de propriedade

Para algumas propriedades de um elemento de objeto, a sintaxe de atributo não é possível, porque o objeto ou as informações necessárias para fornecer o valor da propriedade não podem ser adequadamente expressos dentro das restrições de aspas e cadeia de caracteres da sintaxe de atributo. Para esses casos, uma sintaxe diferente conhecida como sintaxe do elemento de propriedade pode ser usada.

A sintaxe da etiqueta inicial do elemento de propriedade é <TypeName.PropertyName>. Geralmente, o conteúdo dessa tag é um elemento de objeto do tipo que a propriedade toma como seu valor. Depois de especificar o conteúdo, deve-se fechar o elemento de propriedade com uma tag de fecho. A sintaxe da marca final é </TypeName.PropertyName>.

Se uma sintaxe de atributo é possível, usar a sintaxe de atributo normalmente é mais conveniente e permite uma marcação mais compacta, mas isso geralmente é apenas uma questão de estilo, não uma limitação técnica. O exemplo a seguir mostra as mesmas propriedades sendo definidas como no exemplo de sintaxe de atributo anterior, mas desta vez usando a sintaxe do elemento de propriedade para todas as propriedades do Button.

<Button>
    <Button.Background>
        <SolidColorBrush Color="Blue"/>
    </Button.Background>
    <Button.Foreground>
        <SolidColorBrush Color="Red"/>
    </Button.Foreground>
    <Button.Content>
        This is a button
    </Button.Content>
</Button>

Sintaxe da coleção

A linguagem XAML inclui algumas otimizações que produzem marcações mais legíveis por humanos. Uma dessas otimizações é que, se uma determinada propriedade aceita um tipo de coleção, os itens que defines na marcação como elementos filhos dentro do valor dessa propriedade se tornam parte da coleção. Nesse caso, uma coleção de elementos de objetos-filho é o valor que está a ser definido para a propriedade de coleção.

O exemplo a seguir mostra a sintaxe de coleção GradientStops para atribuir valores da propriedade.

<LinearGradientBrush>
    <LinearGradientBrush.GradientStops>
        <!-- no explicit new GradientStopCollection, parser knows how to find or create -->
        <GradientStop Offset="0.0" Color="Red" />
        <GradientStop Offset="1.0" Color="Blue" />
    </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

Propriedades de conteúdo XAML

XAML especifica um recurso de linguagem pelo qual uma classe pode designar exatamente uma de suas propriedades como sendo a propriedade de conteúdo XAML. Os elementos filhos desse elemento objeto são usados para definir o valor dessa propriedade de conteúdo. Em outras palavras, para a propriedade de conteúdo exclusivamente, pode omitir um elemento de propriedade ao definir essa propriedade na marcação XAML e produzir uma metáfora pai/filho mais visível na marcação.

Por exemplo, Border especifica uma propriedade content de Child. Os dois Border elementos seguintes são tratados de forma idêntica. O primeiro aproveita a sintaxe da propriedade de conteúdo e omite o elemento de propriedade Border.Child. A segunda mostra Border.Child explicitamente.

<Border>
    <TextBox Width="300"/>
</Border>
<!--explicit equivalent-->
<Border>
    <Border.Child>
        <TextBox Width="300"/>
    </Border.Child>
</Border>

Como regra da linguagem XAML, o valor de uma propriedade de conteúdo XAML deve ser dado inteiramente antes ou inteiramente depois de quaisquer outros elementos de propriedade nesse elemento de objeto. Por exemplo, a marcação a seguir não é compilada.

<Button>I am a
  <Button.Background>Blue</Button.Background>
  blue button</Button>

Para obter mais informações sobre as especificidades da sintaxe XAML, consulte Sintaxe XAML em detalhes.

Conteúdo do texto

Um pequeno número de elementos XAML pode processar texto diretamente como seu conteúdo. Para permitir isso, um dos seguintes casos deve ser verdadeiro:

  • A classe deve declarar uma propriedade de conteúdo, e essa propriedade de conteúdo deve ser de um tipo atribuível a uma cadeia de caracteres (o tipo pode ser Object). Por exemplo, qualquer ContentControl usa Content como sua propriedade de conteúdo e é do tipo Object, e isso suporta o seguinte uso em um ContentControl como um Button: <Button>Hello</Button>.

  • O tipo deve declarar um conversor de tipo, caso em que o conteúdo do texto é usado como texto de inicialização para esse conversor de tipo. Por exemplo, <Brush>Blue</Brush> converte o valor do conteúdo de Blue em um pincel. Este caso é menos comum na prática.

  • O tipo deve ser uma primitiva de linguagem XAML conhecida.

Propriedades de conteúdo e sintaxe de coleção combinadas

Considere este exemplo.

<StackPanel>
    <Button>First Button</Button>
    <Button>Second Button</Button>
</StackPanel>

Aqui, cada Button um é um elemento filho do StackPanel. Esta é uma marcação simplificada e intuitiva que omite duas tags por dois motivos diferentes.

  • Elemento de propriedade StackPanel.Children omitido:StackPanel deriva de Panel. Panel define Panel.Children como sua propriedade de conteúdo XAML.

  • Elemento de objeto UIElementCollection omitido: A propriedade Panel.Children aceita o tipo UIElementCollection, que implementa IList. A marca de elemento da coleção pode ser omitida, com base nas regras XAML para processar coleções como IList. (Neste caso, UIElementCollection na verdade não pode ser instanciado porque não expõe um construtor sem parâmetros, e é por isso que o elemento de objeto UIElementCollection é mostrado como comentado).

<StackPanel>
    <StackPanel.Children>
        <!--<UIElementCollection>-->
        <Button>First Button</Button>
        <Button>Second Button</Button>
        <!--</UIElementCollection>-->
    </StackPanel.Children>
</StackPanel>

Sintaxe do atributo (eventos)

A sintaxe de atributo também pode ser usada para membros que são eventos em vez de propriedades. Nesse caso, o nome do atributo é o nome do evento. Na implementação WPF de eventos para XAML, o valor do atributo é o nome de um manipulador que implementa o delegado desse evento. Por exemplo, a marcação a seguir atribui um manipulador para o evento Click a um Button criado em marcação.

<Button Click="Button_Click" >Click Me!</Button>

Há mais eventos e XAML no WPF do que apenas este exemplo da sintaxe do atributo. Por exemplo, você pode se perguntar o que o ClickHandler referenciado aqui representa e como ele é definido. Isso será explicado na próxima seção Eventos e code-behind XAML deste artigo.

Caso e espaço em branco em XAML

Em geral, o XAML diferencia maiúsculas de minúsculas. Para fins de resolução de tipos de suporte, o WPF XAML diferencia maiúsculas de minúsculas pelas mesmas regras que o CLR diferencia maiúsculas de minúsculas. Elementos de objeto, elementos de propriedade e nomes de atributos devem ser especificados usando o invólucro sensível quando comparados por nome com o tipo subjacente no assembly ou com um membro de um tipo. Palavras-chave e primitivas da linguagem XAML também diferenciam maiúsculas de minúsculas. Os valores nem sempre são sensíveis a maiúsculas e minúsculas. A diferenciação de maiúsculas e minúsculas para valores dependerá do comportamento do conversor de tipo associado à propriedade que obtém o valor ou do tipo de valor da propriedade. Por exemplo, as propriedades que usam o Boolean tipo podem ter um true ou True como valores equivalentes, mas somente porque a conversão de tipo do analisador WPF XAML nativo para string já permite que estes sejam equivalentes.

Os processadores e serializadores WPF XAML ignorarão ou descartarão todo o espaço em branco não significativo e normalizarão qualquer espaço em branco significativo. Isso é consistente com as recomendações de comportamento de espaço em branco padrão da especificação XAML. Esse comportamento só é conseqüente quando você especifica cadeias de caracteres dentro das propriedades de conteúdo XAML. Em termos mais simples, o XAML converte espaço, alimentação de linhas e caracteres de tabulação em espaços e, em seguida, preserva um espaço se encontrado em qualquer extremidade de uma cadeia de caracteres contígua. A explicação completa da manipulação de espaços em branco XAML não é abordada neste artigo. Para obter mais informações, consulte Processamento de espaço em branco em XAML.

Extensões de marcação

As extensões de marcação são um conceito de linguagem XAML. Quando usadas para fornecer o valor de uma sintaxe de atributo, chaves ({ e }) indicam a utilização de uma extensão de marcação. Esse uso direciona o processamento XAML para escapar do tratamento geral de valores de atributo como uma cadeia de caracteres literal ou um valor conversível em cadeia de caracteres.

As extensões de marcação mais comuns usadas na programação de aplicativos WPF são Binding, usadas para expressões de vinculação de dados e as referências StaticResource de recursos e DynamicResource. Usando extensões de marcação, você pode usar a sintaxe de atributo para fornecer valores para propriedades, mesmo que essa propriedade não ofereça suporte a uma sintaxe de atributo em geral. As extensões de marcação geralmente usam tipos de expressão intermediários para habilitar recursos como adiamento de valores ou referência a outros objetos que só estão presentes em tempo de execução.

Por exemplo, a marcação a seguir define o valor da propriedade com a sintaxe do atributo Style. A Style propriedade usa uma instância da Style classe, que por padrão não pôde ser instanciada por uma cadeia de sintaxe de atributo. Mas, neste caso, o atributo faz referência a uma extensão de marcação específica, StaticResource. Quando essa extensão de marcação é processada, ela retorna uma referência a um estilo que foi instanciado anteriormente como um recurso com chave em um dicionário de recursos.

<Window x:Class="index.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Height="100" Width="300">
    <Window.Resources>
        <SolidColorBrush x:Key="MyBrush" Color="Gold"/>
        <Style TargetType="Border" x:Key="PageBackground">
            <Setter Property="BorderBrush" Value="Blue"/>
            <Setter Property="BorderThickness" Value="5" />
        </Style>
    </Window.Resources>
    <Border Style="{StaticResource PageBackground}">
        <StackPanel>
            <TextBlock Text="Hello" />
        </StackPanel>
    </Border>
</Window>

Para obter uma lista de referência de todas as extensões de marcação para XAML implementadas especificamente no WPF, consulte Extensões WPF XAML. Para obter uma lista de referência das extensões de marcação definidas por System.Xaml e mais amplamente disponíveis para implementações XAML .NET, consulte Recursos de linguagem XAML Namespace (x:). Para obter mais informações sobre conceitos de extensão de marcação, consulte Extensões de marcação e WPF XAML.

Conversores de tipo

Na seção Sintaxe XAML em resumo , foi afirmado que o valor do atributo deve ser capaz de ser definido por uma cadeia de caracteres. A manipulação básica e nativa de como as strings são convertidas em outros tipos de objeto ou valores primitivos é baseada no próprio tipo, juntamente com processamento nativo para certos tipos, como String ou DateTime. Mas muitos tipos WPF ou membros desses tipos estendem o comportamento básico de processamento de atributos de cadeia de caracteres de tal forma que instâncias de tipos de objeto mais complexos podem ser especificadas como cadeias de caracteres e atributos.

A Thickness estrutura é um exemplo de um tipo que tem uma conversão de tipo habilitada para usos de XAML. Thickness indica medidas dentro de um retângulo aninhado e é usado como o valor para propriedades como Margin. Ao colocar um conversor de tipo no Thickness, todas as propriedades que usam um Thickness são mais fáceis de especificar em XAML porque podem ser especificadas como atributos. O exemplo a seguir usa uma conversão de tipo e sintaxe de atributo para fornecer um valor para um Margin:

<Button Margin="10,20,10,30" Content="Click me"/>

O exemplo de sintaxe de atributo anterior é equivalente ao seguinte exemplo de sintaxe mais detalhado, onde a Margin é definida através da sintaxe do elemento de propriedade que contém um elemento de objeto Thickness. As quatro principais propriedades de Thickness são definidas como atributos na nova instância:

<Button Content="Click me">
    <Button.Margin>
        <Thickness Left="10" Top="20" Right="10" Bottom="30"/>
    </Button.Margin>
</Button>

Observação

Há também um número limitado de objetos em que a conversão de tipo é a única maneira pública de definir uma propriedade para esse tipo sem envolver uma subclasse, porque o tipo em si não tem um construtor sem parâmetros. Um exemplo é Cursor.

Para obter mais informações sobre conversão de tipo, consulte TypeConverters e XAML.

Elementos principais e namespaces

Um arquivo XAML deve ter apenas um elemento raiz, para ser um arquivo XML bem formado e um arquivo XAML válido. Para cenários típicos do WPF, você usa um elemento raiz que tem um significado proeminente no modelo de aplicativo WPF (por exemplo, Window ou Page para uma página, ResourceDictionary para um dicionário externo ou Application para a definição do aplicativo). O exemplo a seguir mostra o elemento raiz de um arquivo XAML típico para uma página WPF, com o elemento raiz de Page.

<Page x:Class="index.Page1"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="Page1">

</Page>

O elemento raiz também contém os atributos xmlns e xmlns:x. Esses atributos indicam a um processador XAML quais namespaces XAML contêm as definições de tipo para tipos de suporte aos quais a marcação fará referência como elementos. O xmlns atributo indica especificamente o namespace XAML padrão. Dentro do namespace XAML padrão, os elementos de objeto na marcação podem ser especificados sem um prefixo. Para a maioria dos cenários de aplicativo WPF e para quase todos os exemplos fornecidos nas seções WPF do SDK, o namespace XAML padrão é mapeado para o namespace http://schemas.microsoft.com/winfx/2006/xaml/presentationWPF. O xmlns:x atributo indica um namespace XAML adicional, que mapeia o namespace http://schemas.microsoft.com/winfx/2006/xamlda linguagem XAML.

Esse uso de xmlns para definir um escopo para uso e mapeamento de um namescope é consistente com a especificação XML 1.0. Os namescopes XAML são diferentes dos namescopes XML apenas porque um namescope XAML também implica algo sobre como os elementos do namescope são apoiados por tipos quando se trata de resolução de tipos e análise do XAML.

Os xmlns atributos são estritamente necessários apenas no elemento raiz de cada arquivo XAML. xmlns as definições se aplicarão a todos os elementos descendentes do elemento raiz (esse comportamento é novamente consistente com a especificação XML 1.0 para xmlns.) xmlns atributos também são permitidos em outros elementos abaixo da raiz e se aplicariam a quaisquer elementos descendentes do elemento definidor. No entanto, a definição ou redefinição frequente de namespaces XAML pode resultar em um estilo de marcação XAML difícil de ler.

A implementação WPF de seu processador XAML inclui uma infraestrutura que tem conhecimento dos assemblies principais do WPF. Os assemblies principais do WPF são conhecidos por conter os tipos que suportam os mapeamentos WPF para o namespace XAML padrão. Isso é habilitado por meio da configuração que faz parte do arquivo de compilação do projeto e dos sistemas de compilação e projeto do WPF. Portanto, declarar o namespace padrão XAML como o padrão é tudo o que é necessário para referenciar elementos XAML provenientes de coleções WPF.

O prefixo x:

No exemplo de elemento raiz anterior, o prefixo x: foi usado para mapear o namespace http://schemas.microsoft.com/winfx/2006/xamlXAML , que é o namespace XAML dedicado que suporta construções de linguagem XAML. Esse x: prefixo é usado para mapear esse namespace XAML nos modelos para projetos, em exemplos e na documentação em todo este SDK. O namespace XAML para a linguagem XAML contém várias construções de programação que você usará com freqüência em seu XAML. A seguir está uma lista das construções de programação de prefixo mais comuns x: que você usará:

  • x:Key: Define uma chave exclusiva para cada recurso em um ResourceDictionary (ou conceitos de dicionário semelhantes em outras estruturas). Provavelmente x:Key será responsável por 90% das utilizações de x: que o utilizador verá na marcação de uma aplicação WPF típica.

  • x:Class: Especifica o namespace CLR e o nome da classe para a classe que fornece code-behind para uma página XAML. Você deve ter essa classe para suportar code-behind de acordo com o modelo de programação WPF e, portanto, você quase sempre vê x: mapeado, mesmo que não haja recursos.

  • x:Name: Especifica um nome de objeto em tempo de execução para a instância que existe no código de tempo de execução depois que um elemento de objeto é processado. Em geral, você usará frequentemente uma propriedade equivalente definida pelo WPF para x:Name. Essas propriedades são mapeadas especificamente para uma propriedade de suporte CLR e, portanto, são mais convenientes para a programação de aplicativos, onde você frequentemente usa código em tempo de execução para localizar os elementos nomeados do XAML inicializado. A propriedade mais comum é FrameworkElement.Name. Você ainda pode usar x:Name quando a propriedade equivalente no nível Name de estrutura do WPF não é suportada em um tipo específico. Isso ocorre em determinados cenários de animação.

  • x:Static: habilita uma referência que retorna um valor estático que, de outra forma, não é uma propriedade compatível com XAML.

  • x:Type: Constrói uma Type referência com base em um nome de tipo. Isso é usado para especificar atributos que usam Type, como Style.TargetType, embora frequentemente a propriedade tenha conversão nativa de cadeia de caracteres para Type de tal forma que o uso da extensão de marcação x:Type seja opcional.

Há construções de programação adicionais no namespace prefix/ x: XAML, que não são tão comuns. Para obter detalhes, consulte Recursos de linguagem XAML Namespace (x:).

Prefixos e tipos personalizados

Para as suas próprias assemblies personalizadas, ou para assemblies fora do núcleo WPF de PresentationCore, PresentationFramework e WindowsBase, pode especificar o assembly como parte de um mapeamento personalizado xmlns. Em seguida, você pode fazer referência a tipos desse assembly em seu XAML, desde que esse tipo seja implementado corretamente para dar suporte aos usos de XAML que você está tentando.

A seguir está um exemplo básico de como os prefixos personalizados funcionam na marcação XAML. O prefixo custom é definido na marca do elemento raiz e associado a um conjunto específico que é empacotado e disponível com a aplicação. Este assembly contém um tipo NumericUpDown, que é implementado para suportar o uso geral de XAML, bem como a utilização de uma herança de classe que permite a sua inserção neste ponto específico em um modelo de conteúdo XAML WPF. Uma instância desse NumericUpDown controle é declarada como um elemento de objeto, usando o prefixo para que um analisador XAML saiba qual namespace XAML contém o tipo e, portanto, onde está o assembly de suporte que contém a definição de tipo.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:custom="clr-namespace:NumericUpDownCustomControl;assembly=CustomLibrary"
    >
  <StackPanel Name="LayoutRoot">
    <custom:NumericUpDown Name="numericCtrl1" Width="100" Height="60"/>
...
  </StackPanel>
</Page>

Para obter mais informações sobre tipos personalizados em XAML, consulte XAML e classes personalizadas para WPF.

Para obter mais informações sobre como namespaces XML e namespaces de código em assemblies estão relacionados, consulte Namespaces XAML e mapeamento de namespace para WPF XAML.

Eventos e código-behind em XAML

A maioria dos aplicativos WPF consiste em marcação XAML e código subjacente. Dentro de um projeto, o XAML é escrito como um .xaml arquivo e uma linguagem CLR, como Microsoft Visual Basic ou C#, é usada para escrever um arquivo code-behind. Quando um arquivo XAML é marcado compilado como parte da programação WPF e modelos de aplicativo, o local do arquivo code-behind XAML para um arquivo XAML é identificado especificando um namespace e uma classe como o x:Class atributo do elemento raiz do XAML.

Nos exemplos até agora, você viu vários botões, mas nenhum desses botões tinha qualquer comportamento lógico associado a eles ainda. O principal mecanismo de nível de aplicativo para adicionar um comportamento para um elemento object é usar um evento existente da classe de elemento e escrever um manipulador específico para esse evento que é invocado quando esse evento é gerado em tempo de execução. O nome do evento e o nome do manipulador a ser usado são especificados na marcação, enquanto o código que implementa o manipulador é definido no code-behind.

<Page x:Class="ExampleNamespace.ExamplePage"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel>
        <Button Click="Button_Click">Click me</Button>
    </StackPanel>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ExampleNamespace;

public partial class ExamplePage : Page
{
    public ExamplePage() =>
        InitializeComponent();

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        var buttonControl = (Button)e.Source;
        buttonControl.Foreground = Brushes.Red;
    }
}
Class ExamplePage
    Private Sub Button_Click(sender As Object, e As RoutedEventArgs)
        Dim buttonControl = DirectCast(e.Source, Button)
        buttonControl.Foreground = Brushes.Red
    End Sub
End Class

Observe que o arquivo code-behind usa o namespace ExampleNamespace CLR (o namespace não é visível no Visual Basic) e declara ExamplePage como uma classe parcial dentro desse namespace. O valor do atributo x:Class de ExampleNamespace é semelhante. ExamplePage que foi fornecido na raiz de marcação. O compilador de marcação WPF criará uma classe parcial para qualquer arquivo XAML compilado, derivando uma classe do tipo de elemento raiz. Quando você fornece code-behind que também define a mesma classe parcial, o código resultante é combinado dentro do mesmo namespace e classe do aplicativo compilado.

Importante

No Visual Basic, o namespace raiz está implícito tanto para o XAML quanto para o código por trás. Somente namespaces aninhados são visíveis. Este artigo demonstra o XAML do projeto C#.

Para obter mais informações sobre os requisitos para programação "code-behind" no WPF, consulte "Code-behind", Manipulador de Eventos e Requisitos de Classe Parcial no WPF.

Se você não quiser criar um arquivo code-behind separado, também poderá inserir seu código em um arquivo XAML. No entanto, o código inline é uma técnica menos versátil que tem limitações substanciais. Para obter mais informações, consulte Code-Behind e XAML no WPF.

Eventos encaminhados

Um recurso de evento específico que é fundamental para o WPF é um evento roteado. Os eventos roteados permitem que um elemento manipule um evento que foi gerado por um elemento diferente, desde que os elementos estejam conectados por meio de uma relação de árvore. Ao especificar a manipulação de eventos com um atributo XAML, o evento roteado pode ser escutado e manipulado em qualquer elemento, incluindo elementos que não listam esse evento específico na tabela de membros da classe. Isso é feito qualificando o atributo de nome do evento com o nome da classe proprietária. Por exemplo, o elemento pai StackPanel no exemplo em andamento StackPanel / Button pode registrar um manipulador para o evento Click do botão do elemento filho especificando o atributo Button.Click no elemento StackPanel object, usando o nome do manipulador StackPanel como valor do atributo. Para mais informações, consulte Visão geral sobre eventos roteados.

Elementos nomeados

Por padrão, a instância de objeto que é criada em um gráfico de objeto processando um elemento de objeto XAML não tem um identificador exclusivo ou referência de objeto. Por outro lado, se você chamar um construtor no código, quase sempre usará o resultado do construtor para definir uma variável para a instância construída, para que você possa fazer referência à instância posteriormente em seu código. Para fornecer acesso padronizado a objetos que foram criados por meio de uma definição de marcação, o XAML define o atributo x:Name. Você pode definir o valor do atributo x:Name em qualquer elemento de objeto. No code-behind, o identificador escolhido é equivalente a uma variável de instância que se refere à instância construída. Em todos os aspetos, os elementos nomeados funcionam como se fossem instâncias de objeto (o nome faz referência a essa instância), e seu code-behind pode fazer referência aos elementos nomeados para lidar com interações em tempo de execução dentro do aplicativo. Essa conexão entre instâncias e variáveis é realizada pelo compilador de marcação WPF XAML e, mais especificamente, envolve recursos e padrões como InitializeComponent os que não serão discutidos em detalhes neste artigo.

Os elementos XAML no nível da estrutura do WPF herdam uma Name propriedade, que é equivalente ao atributo definido por XAML x:Name . Algumas outras classes também fornecem equivalentes de nível de propriedade para x:Name, que também é geralmente definido como uma Name propriedade. De um modo geral, se você não conseguir encontrar uma Name propriedade na tabela de membros para o elemento/tipo escolhido, use x:Name em vez disso. Os x:Name valores fornecerão um identificador para um elemento XAML que pode ser usado em tempo de execução, seja por subsistemas específicos ou por métodos de utilitários como FindName.

O exemplo a seguir define Name em um StackPanel elemento . Em seguida, um manipulador em um Button dentro de StackPanel faz referência ao StackPanel através da sua referência de instância buttonContainer conforme definido por Name.

<StackPanel Name="buttonContainer">
    <Button Click="RemoveThis_Click">Click to remove this button</Button>
</StackPanel>
private void RemoveThis_Click(object sender, RoutedEventArgs e)
{
    var element = (FrameworkElement)e.Source;
    
    if (buttonContainer.Children.Contains(element))
        buttonContainer.Children.Remove(element);
}
Private Sub RemoveThis_Click(sender As Object, e As RoutedEventArgs)
    Dim element = DirectCast(e.Source, FrameworkElement)

    If buttonContainer.Children.Contains(element) Then
        buttonContainer.Children.Remove(element)
    End If
End Sub

Assim como uma variável, o nome XAML de uma instância é regido por um conceito de escopo, para que os nomes possam ser forçados a serem exclusivos dentro de um determinado escopo que é previsível. A marcação principal que define uma página denota um escopo de nomes XAML exclusivo, com a fronteira do escopo de nomes XAML sendo o elemento raiz dessa página. No entanto, outras fontes de marcação podem interagir com uma página em tempo de execução, como estilos ou modelos dentro de estilos, e essas fontes de marcação geralmente têm seus próprios namescopes XAML que não se conectam necessariamente com o namescope XAML da página. Para obter mais informações sobre x:Name e namescopes XAML, consulte Name, x:Name Directive ou WPF XAML Namescopes.

Propriedades anexadas e eventos anexados

XAML especifica um recurso de linguagem que permite que determinadas propriedades ou eventos sejam especificados em qualquer elemento, mesmo que a propriedade ou evento não exista nas definições do tipo para o elemento em que está sendo definido. A versão de propriedades desse recurso é chamada de propriedade anexada, a versão de eventos é chamada de evento anexado. Conceitualmente, você pode pensar em propriedades anexadas e eventos anexados como membros globais que podem ser definidos em qualquer instância de elemento/objeto XAML. No entanto, esse elemento/classe ou uma infraestrutura maior deve suportar um repositório de propriedades de suporte para os valores associados.

As propriedades anexadas em XAML são normalmente usadas por meio da sintaxe de atributo. Na sintaxe do atributo, você especifica uma propriedade anexada no formulário ownerType.propertyName.

Superficialmente, isto assemelha-se à utilização de um elemento de propriedade, mas, neste caso, o ownerType que especifica é sempre de um tipo diferente daquele do elemento objeto onde a propriedade anexada está a ser configurada. ownerType é o tipo que fornece os métodos de acessador exigidos por um processador XAML para obter ou definir o valor da propriedade anexada.

O cenário mais comum para propriedades anexas é permitir que elementos filho comuniquem um valor de propriedade ao seu elemento pai.

O seguinte exemplo ilustra a propriedade DockPanel.Dock anexada. A DockPanel classe define os acessadores para DockPanel.Dock e possui a propriedade anexada. A DockPanel classe também inclui lógica que itera seus elementos filho e verifica especificamente cada elemento para um valor definido de DockPanel.Dock. Se um valor for encontrado, esse valor será usado durante o layout para posicionar os elementos filho. O uso da propriedade anexada DockPanel.Dock e desta capacidade de posicionamento é, de facto, o cenário motivador para a classe DockPanel.

<DockPanel>
    <Button DockPanel.Dock="Left" Width="100" Height="20">I am on the left</Button>
    <Button DockPanel.Dock="Right" Width="100" Height="20">I am on the right</Button>
</DockPanel>

No WPF, a maioria ou todas as propriedades anexadas também são implementadas como propriedades de dependência. Para obter mais informações, consulte Visão geral das propriedades anexadas.

Os eventos anexados usam uma forma semelhante ownerType.eventName de sintaxe de atributo. Assim como os eventos não anexados, o valor do atributo para um evento anexado em XAML especifica o nome do método manipulador que é invocado quando o evento é manipulado no elemento. Os usos de eventos anexados no WPF XAML são menos comuns. Para obter mais informações, consulte Visão geral de eventos anexados.

Tipos de base

A estrutura subjacente do WPF XAML e o seu namespace XAML associado é uma coleção de tipos que correspondem a objetos CLR e elementos de marcação para o XAML. No entanto, nem todas as classes podem ser mapeadas para elementos. Classes abstratas, como ButtonBase, e certas classes base não abstratas, são usadas para herança no modelo de objetos CLR. As classes base, incluindo as abstratas, ainda são importantes para o desenvolvimento XAML porque cada um dos elementos XAML concretos herda membros de alguma classe base em sua hierarquia. Muitas vezes, esses membros incluem propriedades que podem ser definidas como atributos no elemento ou eventos que podem ser manipulados. FrameworkElement é a classe de interface do usuário base concreta do WPF no nível da estrutura do WPF. Ao projetar a interface do usuário, você usará várias classes de forma, painel, decorador ou controle, que derivam do FrameworkElement. Uma classe base relacionada, FrameworkContentElement, suporta elementos orientados a documentos que funcionam bem para uma apresentação de layout de fluxo, usando APIs que espelham deliberadamente as APIs no FrameworkElement. A combinação de atributos no nível do elemento e um modelo de objeto CLR fornece um conjunto de propriedades comuns que são configuráveis na maioria dos elementos XAML concretos, independentemente do elemento XAML específico e seu tipo subjacente.

Segurança

XAML é uma linguagem de marcação que representa diretamente a instanciação e a execução de objetos. É por isso que os elementos criados em XAML têm a mesma capacidade de interagir com recursos do sistema (acesso à rede, E/S do sistema de arquivos, por exemplo) que o código do seu aplicativo. O XAML também tem o mesmo acesso aos recursos do sistema que o aplicativo de hospedagem.

Segurança de acesso ao código (CAS) no WPF

Ao contrário do .NET Framework, o WPF para .NET não suporta CAS. Para obter mais informações, consulte Diferenças de segurança de acesso ao código.

Carregar XAML a partir de código

O XAML pode ser usado para definir toda a interface do usuário, mas às vezes também é apropriado definir apenas uma parte da interface do usuário em XAML. Esta capacidade pode ser utilizada para:

  • Habilite a personalização parcial.
  • Armazenamento local de informações da interface do usuário.
  • Modele um objeto de negócios.

A chave para esses cenários é a XamlReader classe e seu Load método. A entrada é um arquivo XAML e a saída é um objeto que representa toda a árvore de tempo de execução de objetos que foi criada a partir dessa marcação. Em seguida, você pode inserir o objeto para ser uma propriedade de outro objeto que já existe no aplicativo. Desde que a propriedade esteja no modelo de conteúdo e tenha recursos de exibição que notificarão o mecanismo de execução de que um novo conteúdo foi adicionado ao aplicativo, você pode modificar o conteúdo de um aplicativo em execução facilmente carregando dinamicamente em XAML.

Ver também