Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este artigo descreve os recursos da linguagem XAML e demonstra como você pode usar XAML para escrever aplicativos do WPF (Windows Presentation Foundation). Este artigo descreve especificamente o XAML, conforme implementado pelo WPF. O XAML em si é um conceito de linguagem maior que o WPF.
O que é XAML
O XAML é uma linguagem de marcação declarativa. Conforme aplicado ao modelo de programação do .NET, o XAML simplifica a criação de uma interface do usuário para um aplicativo .NET. Você pode criar elementos de interface do usuário visíveis 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 parciais de classe. O 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 interpretada sem uma associação direta a um sistema de tipos de suporte. O XAML habilita um fluxo de trabalho em que 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 fornecer um sabor de como o XAML representa metáforas comuns de programação de interface do usuário (não é uma amostra completa).
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Sintaxe XAML em breve
As seções a seguir explicam as formas básicas de sintaxe XAML e dão um exemplo de marcação curta. Essas seções não se destinam a fornecer informações completas sobre cada formulário de sintaxe, como como elas são representadas no sistema de tipos de backup. Para obter mais informações sobre as especificidades da sintaxe XAML, consulte A 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 do objeto XAML
Um elemento de objeto normalmente declara uma instância de um tipo. Esse tipo é definido nos conjuntos referenciados pela tecnologia que utiliza XAML como linguagem.
A sintaxe do elemento objeto sempre começa com um colchete de ângulo de abertura (<
). Isso é seguido pelo nome do tipo em que você deseja criar uma instância. (O nome pode incluir um prefixo, um conceito que será explicado posteriormente.) Depois disso, opcionalmente, você pode declarar atributos no elemento de objeto. Para concluir a marca de elemento de objeto, termine com um colchete de ângulo de fechamento (>
). Em vez disso, você pode usar uma tag de autofechamento que não tem nenhum conteúdo, completando a tag com uma barra para frente e um colchete de ângulo de fechamento em sucessão (/>
). Por exemplo, examine novamente o trecho de código de marcação mostrado anteriormente.
<StackPanel>
<Button Content="Click Me"/>
</StackPanel>
Isso especifica dois elementos de objeto: <StackPanel>
(com conteúdo e uma marca de fechamento posterior) e <Button .../>
(o formulário de auto-fechamento, com vários atributos). Os elementos StackPanel
e Button
cada um mapeia para o nome de uma classe que é definida pelo WPF e faz parte dos assemblies do WPF. Ao especificar uma marca de elemento de objeto, você cria uma instrução para o 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 de atributo (propriedades)
As propriedades de um objeto geralmente podem ser expressas como atributos do elemento de objeto. 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 que está contida entre aspas.
A sintaxe de atributo é a sintaxe de configuração de propriedade mais simplificada e é a sintaxe mais intuitiva a ser usada para desenvolvedores que usaram idiomas de marcação no passado. Por exemplo, a marcação a seguir cria um botão que tem 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 property
Para algumas propriedades de um elemento de objeto, a sintaxe de atributo não é possível, pois o objeto ou as informações necessárias para fornecer o valor da propriedade não podem ser expressas adequadamente dentro da aspa e restrições de cadeia de caracteres da sintaxe de atributo. Para esses casos, uma sintaxe diferente conhecida como sintaxe de elemento de propriedade pode ser usada.
A sintaxe da marca inicial do elemento de propriedade é <TypeName.PropertyName>
. Geralmente, o conteúdo dessa tag é um elemento de objeto do tipo que a propriedade assume como seu valor. Depois de especificar o conteúdo, você deve fechar o elemento de propriedade com uma marca final. A sintaxe da marca final é </TypeName.PropertyName>
.
Se uma sintaxe de atributo for possível, usar a sintaxe de atributo normalmente será mais conveniente e habilitará 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 que estão 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 uma marcação mais legível por humanos. Uma dessas otimizações é que, se uma propriedade específica aceita um tipo de coleção, os itens que você declara na marcação como elementos filho desse valor tornam-se parte da coleção. Nesse caso, uma coleção de elementos de objeto filho é o valor que está sendo definido como a propriedade da coleção.
O exemplo a seguir mostra a sintaxe da coleção para definir valores da GradientStops 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
O XAML especifica um recurso de linguagem pelo qual uma classe pode designar exatamente uma de suas propriedades para ser a propriedade de conteúdo XAML. Elementos filho desse elemento de objeto são usados para definir o valor dessa propriedade de conteúdo. Em outras palavras, para a propriedade de conteúdo exclusivamente, você 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 de conteúdo de Child. Os dois Border elementos a seguir 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
. O segundo 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 fornecido 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 A sintaxe XAML em detalhes.
Conteúdo de texto
Um pequeno número de elementos XAML pode processar diretamente o texto como seu conteúdo. Para habilitar 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 dá suporte ao 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 deBlue
em um pincel. Esse caso é menos comum na prática.O tipo deve ser um primitivo de linguagem XAML conhecido.
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 de StackPanel. Essa é uma marcação simplificada e intuitiva que omite duas tags por motivos diferentes.
Elemento de propriedade Omitted StackPanel.Children:StackPanel deriva de Panel. Panel define Panel.Children como sua propriedade de conteúdo XAML.
Elemento de objeto UIElementCollection omitido: A propriedade Panel.Children recebe o tipo UIElementCollection, que implementa IList. A marca de elemento da coleção pode ser omitida, com base nas regras XAML para processamento de coleções como IList. (Nesse caso, na verdade, UIElementCollection não pode ser instanciado porque não oferece um construtor sem parâmetros, e é por isso que o elemento de objeto UIElementCollection é mostrado comentado).
<StackPanel>
<StackPanel.Children>
<!--<UIElementCollection>-->
<Button>First Button</Button>
<Button>Second Button</Button>
<!--</UIElementCollection>-->
</StackPanel.Children>
</StackPanel>
Sintaxe de 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 de eventos do WPF 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 na marcação.
<Button Click="Button_Click" >Click Me!</Button>
Há mais em eventos e XAML no WPF do que apenas este exemplo da sintaxe de 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 XAML code-behind deste artigo.
Uso de maiúsculas, minúsculas e espaços em branco no XAML
Em geral, o XAML diferencia maiúsculas de minúsculas. Para fins de resolução de tipos de backup, o XAML do WPF 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 atributo devem ser especificados usando a maiúscula sensível quando comparados por nome ao tipo subjacente no assembly ou a um membro de um tipo. As palavras-chave e os elementos básicos da linguagem XAML também são sensíveis à diferença entre maiúsculas e minúsculas. Os valores nem sempre diferenciam maiúsculas de minúsculas. A diferenciação entre maiúsculas e minúsculas para valores dependerá do comportamento do conversor de tipo associado à propriedade que recebe o valor ou ao tipo do valor da propriedade. Por exemplo, as propriedades que assumem o tipo Boolean podem ter true
ou True
como valores equivalentes, mas apenas porque a conversão de tipo nativa do analisador XAML do WPF de cadeia de caracteres para Boolean já permite esses como equivalentes.
Os processadores XAML do WPF e os serializadores ignorarão ou removerão todo o espaço em branco não insignificante e normalizarão qualquer espaço em branco significativo. Isso é consistente com as recomendações padrão de comportamento de espaço em branco da especificação XAML. Esse comportamento só é consequência quando você especifica cadeias de caracteres dentro das propriedades de conteúdo XAML. Em termos mais simples, o XAML converte caracteres de espaço, de linha e de tabulação em espaços e preserva um espaço se encontrado em qualquer extremidade de uma cadeia de caracteres contígua. A explicação completa do tratamento de espaço em branco XAML não é abordada neste artigo. Para obter mais informações, consulte Processamento de espaço em branco no XAML.
Extensões de marcação
As extensões de marcação são um conceito de linguagem XAML. Quando usado para fornecer o valor de uma sintaxe de atributo, colchetes ({
e }
) indicam um uso de extensão de marcação. Esse uso direciona o processamento XAML para evitar o tratamento padrão dos valores de atributo como uma string literal ou um valor que pode ser convertido em string.
As extensões de marcação mais comuns usadas na programação de aplicativos do WPF são Binding
usadas para expressões de associação de dados e as referências StaticResource
de recurso 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 dê suporte a uma sintaxe de atributo em geral. As extensões de marcação geralmente usam tipos de expressão intermediária para habilitar recursos como adiar valores ou referenciar outros objetos que só estão presentes em tempo de execução.
Por exemplo, a marcação a seguir define o valor da Style propriedade usando a sintaxe de atributo. A Style propriedade usa uma instância da Style classe, que por padrão não pôde ser instanciada por uma cadeia de caracteres de sintaxe de atributo. Mas, nesse 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 anteriormente instanciado como um recurso 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 listagem de referência de todas as extensões de marcação para XAML implementadas especificamente no WPF, consulte Extensões XAML do WPF. Para obter uma listagem de referência das extensões de marcação definidas pelo System.Xaml e que estão mais amplamente disponíveis para implementações de XAML do .NET, consulte Recursos de linguagem XAML Namespace (x:). Para obter mais informações sobre os conceitos de extensão de marcação, consulte Extensões de Marcação e XAML do WPF.
Conversores de tipo
Na sintaxe XAML na seção Brief , foi declarado que o valor do atributo deve ser capaz de ser definido por uma cadeia de caracteres. A manipulação nativa básica de como as cadeias de caracteres são convertidas em outros tipos de objeto ou valores primitivos é baseada no tipo em si, juntamente com o processamento nativo para tipos específicos, como String ou DateTime. Mas muitos tipos de WPF ou membros desses tipos estendem o comportamento básico de processamento de atributo de cadeia de caracteres de forma que instâncias de tipos de objeto mais complexos possam 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 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 em Thickness, todas as propriedades que usam um Thickness são mais fáceis de especificar em XAML porque podem ser definidas como atributos. O exemplo a seguir usa uma conversão de tipo e uma 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, em que o Margin é definido usando a sintaxe de elemento de propriedade que contém um elemento de objeto Thickness. As quatro propriedades principais 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 próprio tipo 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 raiz 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 do 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 do 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 que 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 do WPF do SDK, o namespace XAML padrão é mapeado para o namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation
do WPF. O xmlns:x
atributo indica um namespace XAML adicional, que mapeia o namespace http://schemas.microsoft.com/winfx/2006/xaml
da linguagem XAML.
Esse uso de xmlns
para definir um escopo para o 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 no elemento raiz de cada arquivo XAML.
xmlns
as definições serão aplicadas a todos os elementos descendentes do elemento raiz (esse comportamento é novamente consistente com a especificação XML 1.0 para xmlns
.) Os atributos xmlns
também são permitidos em outros elementos localizados 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 do WPF de seu processador XAML inclui uma infraestrutura que tem reconhecimento dos assemblies principais do WPF. Os assemblies principais do WPF são conhecidos por conter os tipos que dão suporte aos mapeamentos do WPF para o namespace XAML padrão. Isso é habilitado por meio da configuração que faz parte do arquivo de build do projeto e dos sistemas de build e projeto do WPF. Portanto, declarar o namespace XAML padrão como o padrão xmlns
é tudo o que é necessário para referenciar elementos XAML provenientes de assemblies 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/xaml
XAML, que é o namespace XAML dedicado que dá suporte a constructos de linguagem XAML. Esse x:
prefixo é usado para mapear esse namespace XAML nos modelos para projetos, em exemplos, e na documentação em todo esse SDK. O namespace XAML para a linguagem XAML contém vários constructos de programação que você usará com frequência em seu XAML. Veja a seguir uma listagem dos constructos 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).
x:Key
provavelmente será responsável por 90% dosx:
usos que você verá na marcação de um aplicativo WPF típico.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 dar suporte a code-behind de acordo com o modelo de programação do WPF e, portanto, você quase sempre verá
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 em 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 do CLR e, portanto, são mais convenientes para a programação de aplicativos, onde você frequentemente utiliza código durante a execução para localizar os elementos nomeados do XAML inicializado. A propriedade mais comum desse tipo é FrameworkElement.Name. Você ainda poderá usar x:Name quando a propriedade equivalente no nível Name da estrutura do WPF não tiver suporte 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 levam Type, como Style.TargetType, embora frequentemente a propriedade tenha conversão nativa de cadeia de caracteres para Type, de forma que o uso da marcação de extensão x:Type seja opcional.
Há construções de programação adicionais no x:
namespace prefixo/XAML, que não são tão comuns. Para obter detalhes, consulte os recursos de linguagem XAML Namespace (x:).
Prefixos personalizados e tipos personalizados
Para seus próprios assemblies personalizados ou para assemblies fora do núcleo do WPF, que inclui PresentationCore, PresentationFramework e WindowsBase, é possível especificar o assembly como parte de um mapeamento personalizado xmlns
. Em seguida, você pode referenciar tipos desse assembly em seu XAML, desde que esse tipo seja implementado corretamente para dar suporte aos usos XAML que você está tentando.
Veja a seguir um exemplo básico de como os prefixos personalizados funcionam na marcação XAML. O prefixo custom
é definido na tag do elemento raiz e mapeado para um assembly específico que está empacotado e disponível para o aplicativo. Esse assembly contém um tipo NumericUpDown
, que é implementado para dar suporte ao uso geral de XAML, bem como usar uma herança de classe que permite sua inserção neste ponto específico em um modelo de conteúdo XAML do 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 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 XAML
A maioria dos aplicativos WPF consiste em marcação XAML e código subjacente. Em um projeto, o XAML é escrito como um .xaml
arquivo e uma linguagem CLR como o Microsoft Visual Basic ou C# é usada para escrever um arquivo code-behind. Quando um arquivo XAML é compilado como marcação dentro dos modelos de programação e aplicativo do WPF, o local do arquivo code-behind é identificado especificando-se um namespace e uma classe como atributo x:Class
do elemento raiz do XAML.
Nos exemplos até agora, você viu vários botões, mas nenhum desses botões teve nenhum comportamento lógico associado a eles ainda. O mecanismo principal no nível do aplicativo para adicionar um comportamento para um elemento de objeto é usar um evento existente da classe de elemento e gravar 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 está visível no Visual Basic) e declara ExamplePage
como uma classe parcial dentro desse namespace. Isso corresponde ao valor do atributo x:Class
de ExampleNamespace
.
ExamplePage
que foi fornecido na raiz de marcação. O compilador de marcação do 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 espaço de nomes raiz é implícito tanto para o XAML quanto para o código subjacente. Somente namespaces aninhados estão visíveis. Este artigo demonstra o XAML do projeto C#.
Para obter mais informações sobre os requisitos de programação code-behind no WPF, consulte Code-behind, Manipulador de Eventos e Requisitos parciais de classe 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 embutido é uma técnica menos versátil que tem limitações substanciais. Para obter mais informações, consulte Code-Behind e XAML no WPF.
Eventos roteados
Um recurso de evento específico que é fundamental para o WPF é um evento roteado. Eventos roteados permitem que um elemento manipule um evento que foi gerado por um elemento diferente, desde que os elementos sejam conectados por meio de uma relação hierárquica. Ao especificar o tratamento 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 ao qualificar o atributo de nome do evento com o nome da classe que o possui. Por exemplo, o 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 de objeto StackPanel
, com o nome do seu manipulador como valor do atributo. Para obter mais informações, consulte Visão geral de eventos roteados.
Elementos nomeados
Por padrão, a instância de objeto criada em um grafo de objeto processando um elemento de objeto XAML não tem um identificador exclusivo ou uma 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, de modo que você possa referenciar a 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 x:Name
atributo 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 aspectos, os elementos nomeados funcionam como se fossem instâncias de objeto (o nome faz referência a essa instância) e o code-behind pode referenciar os 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 XAML do WPF e, mais especificamente, envolve recursos e padrões como InitializeComponent esse 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 x:Name
por XAML. Determinadas outras classes também fornecem equivalentes de nível de propriedade para x:Name
, que também geralmente é definido como uma Name
propriedade. De 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 utilitários como FindName.
O exemplo a seguir define o elemento Name em um StackPanel. Em seguida, um manipulador em um Button dentro de StackPanel referencia o StackPanel através de sua instância buttonContainer
, conforme configurado 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 impostos para serem exclusivos dentro de um determinado escopo previsível. A marcação primária que define uma página denota um namescope XAML exclusivo, com o limite do namescope 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 necessariamente se conectam com o namescope XAML da página. Para obter mais informações sobre x:Name
e namescopes XAML, consulte Name, diretiva x:Name ou namescopes XAML do WPF.
Propriedades anexadas e eventos anexados
O 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 dar suporte a um repositório de propriedades de backup para os valores anexados.
As propriedades anexadas em XAML normalmente são usadas por meio da sintaxe de atributo. Na sintaxe do atributo, você especifica uma propriedade anexada no formulário ownerType.propertyName
.
Superficialmente, isso se assemelha a um uso de elemento de propriedade, mas, nesse caso, o ownerType
que você especifica é sempre um tipo diferente do elemento de objeto em que a propriedade anexada está sendo definida.
ownerType
é o tipo que fornece os métodos acessadores exigidos por um processador XAML para obter ou definir o valor da propriedade anexada.
O cenário mais comum para propriedades anexadas é permitir que elementos filho relatem um valor de propriedade ao elemento pai.
O exemplo a seguir ilustra a DockPanel.Dock propriedade anexada. A DockPanel classe define os acessadores para DockPanel.Dock e possui a propriedade anexada. A DockPanel classe também inclui a lógica que itera seus elementos filho e verifica especificamente cada elemento quanto a 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 DockPanel.Dock propriedade anexada e dessa capacidade de posicionamento é, de fato, o motivo 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 de 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 de manipulador que é invocado quando o evento é tratado no elemento. Usos de eventos anexados no WPF XAML são menos comuns. Para obter mais informações, consulte Visão geral de eventos anexados.
Tipos base
O XAML subjacente do WPF e seu namespace são um conjunto de tipos que correspondem a objetos CLR e elementos de marcação para XAML. No entanto, nem todas as classes podem ser mapeadas para elementos. Classes abstratas, como ButtonBase, e determinadas classes base não abstratas, são usadas para herança no modelo de objetos CLR. 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. Geralmente, 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, das quais todas derivam.FrameworkElement Uma classe base relacionada FrameworkContentElement dá suporte a elementos orientados a documentos que funcionam bem para uma apresentação de layout em fluxo, usando APIs que deliberadamente espelham as APIs em 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 do objeto. É por isso que os elementos criados no XAML têm a mesma capacidade de interagir com os recursos do sistema (acesso à rede, E/S do sistema de arquivos, por exemplo) como o código do aplicativo. O XAML também tem o mesmo acesso aos recursos do sistema que o aplicativo de hospedagem.
CAS (Code Access Security) no WPF
Ao contrário do .NET Framework, o WPF para .NET não dá suporte ao CAS. Para obter mais informações, consulte as diferenças de segurança de acesso ao código.
Carregar XAML do 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. Essa funcionalidade pode ser usada 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. Enquanto a propriedade estiver no modelo de conteúdo e tiver recursos de exibição que notificarão o mecanismo de execução de que o novo conteúdo foi adicionado ao aplicativo, você poderá modificar o conteúdo de um aplicativo em execução facilmente carregando dinamicamente no XAML.
Consulte também
- Sintaxe XAML em detalhes
- XAML e classes personalizadas para WPF
- Recursos da linguagem (x:) do namespace de XAML
- Extensões XAML WPF
- Visão geral dos elementos base
- árvores no WPF
.NET Desktop feedback