WPF - Guia rápido

WPF significa Windows Presentation Foundation. É uma estrutura poderosa para construir aplicativos Windows. Este tutorial explica os recursos que você precisa entender para construir aplicativos WPF e como isso traz uma mudança fundamental nos aplicativos do Windows.

O WPF foi introduzido pela primeira vez na versão 3.0 do .NET framework e, em seguida, muitos outros recursos foram adicionados nas versões subsequentes do .NET framework.

Arquitetura WPF

Antes do WPF, as outras estruturas de interface do usuário oferecidas pela Microsoft, como os formulários MFC e Windows, eram apenas invólucros em torno de DLLs User32 e GDI32, mas o WPF faz uso mínimo do User32. Então,

  • O WPF é mais do que apenas um invólucro.
  • É uma parte da estrutura .NET.
  • Ele contém uma mistura de código gerenciado e não gerenciado.

Os principais componentes da arquitetura WPF são mostrados na figura abaixo. A parte de código mais importante do WPF é -

  • Estrutura de apresentação
  • Apresentação
  • Milcore

o presentation framework e a presentation core foram escritos em código gerenciado. Milcore é uma parte do código não gerenciado que permite uma forte integração com o DirectX (responsável pela exibição e renderização). CLR torna o processo de desenvolvimento mais produtivo, oferecendo muitos recursos, como gerenciamento de memória, tratamento de erros, etc.

WPF - Vantagens

Nas estruturas GUI anteriores, não havia separação real entre a aparência de um aplicativo e como ele se comportava. Tanto a GUI quanto o comportamento foram criados na mesma linguagem, por exemplo, C # ou VB.Net, o que exigiria mais esforço do desenvolvedor para implementar a interface do usuário e o comportamento associado a ela.

No WPF, os elementos da interface do usuário são projetados em XAML enquanto os comportamentos podem ser implementados em linguagens procedurais, como C # e VB.Net. Portanto, é muito fácil separar o comportamento do código do designer.

Com o XAML, os programadores podem trabalhar em paralelo com os designers. A separação entre uma GUI e seu comportamento pode nos permitir alterar facilmente a aparência de um controle usando estilos e modelos.

WPF - Recursos

WPF é uma estrutura poderosa para criar aplicativos do Windows. Suporta muitos recursos excelentes, alguns dos quais estão listados abaixo -

Característica Descrição
Controle dentro de um controle Permite definir um controle dentro de outro controle como um conteúdo.
Ligação de dados Mecanismo para exibir e interagir com dados entre os elementos da IU e o objeto de dados na interface do usuário.
Serviços de mídia Fornece um sistema integrado para construir interfaces de usuário com elementos de mídia comuns, como imagens, áudio e vídeo.
Modelos No WPF você pode definir a aparência de um elemento diretamente com um modelo
Animações Construindo interatividade e movimento na interface do usuário
Entrada alternativa Suporta entrada multitoque no Windows 7 e superior.
Direct3D Permite exibir gráficos mais complexos e temas personalizados

A Microsoft fornece duas ferramentas importantes para o desenvolvimento de aplicativos WPF.

  • Estúdio visual
  • Expression Blend

Ambas as ferramentas podem criar projetos WPF, mas o fato é que o Visual Studio é mais usado por desenvolvedores, enquanto o Blend é usado com mais frequência por designers. Para este tutorial, usaremos principalmente o Visual Studio.

Instalação

A Microsoft fornece uma versão gratuita do Visual Studio que pode ser baixada do VisualStudio .

Baixe os arquivos e siga as etapas fornecidas abaixo para configurar o ambiente de desenvolvimento de aplicativos WPF em seu sistema.

  • Depois que o download for concluído, execute o installer. A seguinte caixa de diálogo será exibida.

  • Clique no Install botão e iniciará o processo de instalação.

  • Assim que o processo de instalação for concluído com êxito, você verá a seguinte caixa de diálogo.

  • Feche esta caixa de diálogo e reinicie o computador, se necessário.

  • Agora abra o Visual Studio a partir do Menu Iniciar, que abrirá a seguinte caixa de diálogo.

  • Assim que tudo estiver pronto, você verá a janela principal do Visual Studio.

Agora você está pronto para construir seu primeiro aplicativo WPF.

Neste capítulo, desenvolveremos um aplicativo WPF Hello World simples. Portanto, vamos começar a implementação simples seguindo as etapas fornecidas a seguir.

  • Clique na opção de menu Arquivo> Novo> Projeto.
  • A seguinte caixa de diálogo será exibida.
  • Em Modelos, selecione Visual C # e no painel do meio, selecione Aplicativo WPF.

  • Dê um nome ao projeto. TipoHelloWorld no campo do nome e clique no botão OK.

  • Por padrão, dois arquivos são criados, um é o XAML arquivo (mainwindow.xaml) e o outro é o CS arquivo (mainwindow.cs)

  • Em mainwindow.xaml, você verá duas subjanelas, uma é a design window e o outro é o source (XAML) window.

  • No aplicativo WPF, há duas maneiras de projetar uma IU para seu aplicativo. Uma é simplesmente arrastar e soltar os elementos da interface do usuário da caixa de ferramentas para a janela Design. A segunda maneira é projetar sua interface do usuário escrevendo marcas XAML para os elementos da interface do usuário. O Visual Studio lida com as marcas XAML quando o recurso arrastar e soltar é usado para o design da IU.

  • No arquivo mainwindow.xaml, as seguintes marcas XAML são gravadas por padrão.

<Window x:Class = "HelloWorld.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid> 
   </Grid> 
	
</Window>
  • Por padrão, uma grade é definida como o primeiro elemento após a página.
  • Vamos para a caixa de ferramentas e arrastar um TextBlock para a janela de design.
  • Você verá o TextBlock na janela de design.
  • Ao olhar para a janela de origem, você verá que o Visual Studio gerou o código XAML do TextBlock para você.

  • Vamos alterar a propriedade Text de TextBlock no código XAML de TextBlock para Hello World.

<Window x:Class = "HelloWorld.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <TextBlock x:Name = "textBlock" HorizontalAlignment = "Left"
         Margin = "235,143,0,0" TextWrapping = "Wrap" Text = "Hello World!"
         VerticalAlignment = "Top" Height = "44" Width = "102" /> 
   </Grid> 
	
</Window>
  • Agora, você verá a mudança na janela de design também.

Quando o código acima for compilado e executado, você verá a seguinte janela.

Parabéns! Você projetou e criou seu primeiro aplicativo WPF.

Uma das primeiras coisas que você encontrará ao trabalhar com o WPF é o XAML. XAML significa Extensible Application Markup Language. É uma linguagem simples e declarativa baseada em XML.

  • Em XAML, é muito fácil criar, inicializar e definir propriedades de objetos com relações hierárquicas.

  • É usado principalmente para projetar GUIs, no entanto, pode ser usado para outros fins também, por exemplo, para declarar fluxo de trabalho no Workflow Foundation.

Sintaxe Básica

Ao criar seu novo projeto WPF, você encontrará parte do código XAML por padrão em MainWindow.xaml, conforme mostrado abaixo.

<Window x:Class = "Resources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid> 
         
   </Grid> 
	
</Window>

O arquivo XAML acima contém diferentes tipos de informações. A tabela a seguir explica resumidamente a função de cada informação.

Em formação Descrição
<Janela É o elemento de objeto de abertura ou contêiner da raiz.
x: Class = "Resources.MainWindow" É uma declaração de classe parcial que conecta a marcação ao código de classe parcial definido por trás.
xmlns = "http://schemas.microsoft.com/win fx / 2006 / xaml / presentation" Mapeia o namespace XAML padrão para cliente / estrutura WPF
xmlns: x = "http://schemas.microsoft.com/w infx / 2006 / xaml" Namespace XAML para linguagem XAML que mapeia para x: prefixo
> Fim do elemento de objeto da raiz

<Grid>

</Grid>

É iniciar e fechar tags de um objeto de grade vazio.
</Window> Fechando o elemento do objeto

As regras de sintaxe para XAML são quase semelhantes a XML. Se você examinar um documento XAML, perceberá que, na verdade, ele é um arquivo XML válido, mas um arquivo XML não é necessariamente um arquivo XAML. É porque em XML, o valor dos atributos deve ser uma string, enquanto em XAML, pode ser um objeto diferente que é conhecido como sintaxe de elemento de propriedade.

  • A sintaxe de um elemento Object começa com um colchete angular esquerdo (<) seguido pelo nome de um objeto, por exemplo, Botão.

  • Defina algumas propriedades e atributos desse elemento de objeto.

  • O elemento Object deve ser fechado por uma barra (/) seguida imediatamente por um colchete angular direito (>).

Exemplo de objeto simples sem elemento filho

<Button/>

Exemplo de elemento de objeto com alguns atributos

<Button Content = "Click Me" Height = "30" Width = "60" />

Exemplo de uma sintaxe alternativa para definir propriedades (sintaxe de elemento de propriedade)

<Button> 
   <Button.Content>Click Me</Button.Content> 
   <Button.Height>30</Button.Height> 
   <Button.Width>60</Button.Width> 
</Button>

Exemplo de objeto com elemento filho: StackPanel contém Textblock como elemento filho

<StackPanel Orientation = "Horizontal"> 
   <TextBlock Text = "Hello"/> 
</StackPanel>

Por que XAML no WPF

O XAML não é apenas o recurso mais conhecido do WPF, mas também um dos recursos mais incompreendidos. Se você tem exposição ao WPF, deve ter ouvido falar do XAML; mas observe os dois fatos menos conhecidos a seguir sobre XAML -

  • WPF não precisa de XAML
  • XAML não precisa de WPF

Na verdade, são peças tecnológicas separáveis. Para entender como isso pode ser, vamos dar uma olhada em um exemplo simples em que um botão é criado com algumas propriedades em XAML.

<Window x:Class = "WPFXAMLOverview.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <Button x:Name = "button" Content = "Click Me" HorizontalAlignment = "Left"  
         Margin = "150" VerticalAlignment = "Top" Width = "75" /> 
   </StackPanel> 
	
</Window>

Caso opte por não usar XAML no WPF, você também pode obter o mesmo resultado da GUI com a linguagem procedural. Vamos dar uma olhada no mesmo exemplo, mas desta vez, vamos criar um botão em C #.

using System.Windows; 
using System.Windows.Controls;  

namespace WPFXAMLOverview { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
			
         // Create the StackPanel 
         StackPanel stackPanel = new StackPanel(); 
         this.Content = stackPanel; 
			
         // Create the Button 
         Button button = new Button();
         button.Content = "Click Me"; 
         button.HorizontalAlignment = HorizontalAlignment.Left; 
         button.Margin = new Thickness(150); 
         button.VerticalAlignment = VerticalAlignment.Top; 
         button.Width = 75; 
         stackPanel.Children.Add(button);  
      } 
   } 
}

Ao compilar e executar o código XAML ou o código C #, você verá a mesma saída mostrada abaixo.

A partir do exemplo acima, está claro que o que você pode fazer em XAML para criar, inicializar e definir propriedades de objetos, as mesmas tarefas também podem ser feitas usando código.

  • XAML é apenas outra maneira simples e fácil de projetar elementos de interface do usuário.

  • Com o XAML, isso não significa que o que você pode fazer para projetar elementos de interface do usuário é a única maneira. Você pode declarar os objetos em XAML ou defini-los usando código.

  • O XAML é opcional, mas, apesar disso, é o cerne do design do WPF.

  • O objetivo do XAML é permitir que designers visuais criem elementos de interface do usuário diretamente.

  • O WPF visa possibilitar o controle de todos os aspectos visuais da interface do usuário a partir da marcação.

Existem muitas tecnologias em que os elementos e componentes são ordenados em uma estrutura de árvore para que os programadores possam manipular facilmente o objeto e alterar o comportamento de um aplicativo. O Windows Presentation Foundation (WPF) possui uma estrutura de árvore abrangente na forma de objetos. No WPF, existem duas maneiras de conceituar uma árvore de objetos completa -

  • Estrutura Lógica da Árvore
  • Estrutura da Árvore Visual

Com a ajuda dessas estruturas de árvore, você pode criar e identificar facilmente o relacionamento entre os elementos da IU. Principalmente, os desenvolvedores e designers do WPF usam a linguagem procedural para criar um aplicativo ou projetam a parte da interface do usuário do aplicativo em XAML tendo em mente a estrutura da árvore do objeto.

Estrutura Lógica da Árvore

Em aplicativos WPF, a estrutura dos elementos da interface do usuário em XAML representa a estrutura lógica da árvore. Em XAML, os elementos básicos da IU são declarados pelo desenvolvedor. A árvore lógica no WPF define o seguinte -

  • Propriedades de dependência
  • Recursos estáticos e dinâmicos
  • Vinculando os elementos em seu nome etc.

Vamos dar uma olhada no exemplo a seguir, no qual um botão e uma caixa de listagem são criados.

<Window x:Class = "WPFElementsTree.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <Button x:Name = "button" Height = "30" Width = "70" Content = "OK" Margin = "20" /> 
		
      <ListBox x:Name = "listBox" Height = "100" Width = "100" Margin = "20"> 
         <ListBoxItem Content = "Item 1" /> 
         <ListBoxItem Content = "Item 2" /> 
         <ListBoxItem Content = "Item 3" /> 
      </ListBox> 
		
   </StackPanel> 
	
</Window>

Se você observar o código XAML, verá uma estrutura de árvore, ou seja, o nó raiz é a janela e dentro do nó raiz, há apenas um filho, que é StackPanel. Mas StackPanel contém dois elementos filho, botão e caixa de listagem. A caixa de listagem possui mais três itens de caixa de listagem filha.

Estrutura da Árvore Visual

No WPF, o conceito de árvore visual descreve a estrutura dos objetos visuais, conforme representado pela Classe Base Visual. Significa todos os elementos da IU que são renderizados na tela de saída.

Quando um programador deseja criar um modelo para um controle específico, ele está realmente renderizando a árvore visual desse controle. A árvore visual também é muito útil para aqueles que desejam desenhar controles de nível inferior por motivos de desempenho e otimização.

Em aplicativos WPF, a árvore visual é usada para -

  • Renderizando os objetos visuais.
  • Renderizando os layouts.
  • Os eventos roteados principalmente viajam ao longo da árvore visual, não a árvore lógica.

Para ver a árvore visual do aplicativo simples acima, que contém um botão e uma caixa de listagem, vamos compilar e executar o código XAML e você verá a janela a seguir.

Quando o aplicativo está em execução, você pode ver a árvore visual do aplicativo em execução na janela Live Visual Tree que mostra a hierarquia completa deste aplicativo, conforme mostrado abaixo.

A árvore visual é normalmente um superconjunto da árvore lógica. Você pode ver aqui que todos os elementos lógicos também estão presentes na árvore visual. Portanto, essas duas árvores são, na verdade, apenas duas visualizações diferentes do mesmo conjunto de objetos que constituem a IU.

  • A árvore lógica deixa de fora muitos detalhes, permitindo que você se concentre na estrutura central da interface do usuário e ignore os detalhes de como exatamente ela foi apresentada.

  • A árvore lógica é o que você usa para criar a estrutura básica da interface do usuário.

  • A árvore visual será interessante se você estiver se concentrando na apresentação. Por exemplo, se você deseja personalizar a aparência de qualquer elemento da IU, você precisará usar a árvore visual.

Em aplicativos WPF, a propriedade de dependência é um tipo específico de propriedade que estende a propriedade CLR. Aproveita as funcionalidades específicas disponíveis no sistema de propriedades WPF.

Uma classe que define uma propriedade de dependência deve ser herdada do DependencyObjectclasse. Muitas das classes de controles de IU que são usadas em XAML são derivadas doDependencyObject classe e eles suportam propriedades de dependência, por exemplo, a classe Button suporta IsMouseOver propriedade de dependência.

O código XAML a seguir cria um botão com algumas propriedades.

<Window x:Class = "WPFDependencyProperty.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFDependencyProperty"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button  Height = "40" Width = "175" Margin = "10" Content = "Dependency Property"> 
         <Button.Style> 
            <Style TargetType = "{x:Type Button}"> 
               <Style.Triggers> 
					
                  <Trigger Property = "IsMouseOver" Value = "True"> 
                     <Setter Property = "Foreground" Value = "Red" /> 
                  </Trigger>
						
               </Style.Triggers>
            </Style> 
         </Button.Style> 
      </Button> 
   </Grid> 
	
</Window>

A extensão de marcação x: Type em XAML tem uma funcionalidade semelhante, como typeof () em C #. É usado quando são especificados atributos que assumem o tipo do objeto, como <Style TargetType = "{x: Type Button}">

Quando o código acima for compilado e executado, você obterá o seguinte MainWindow. Quando o mouse estiver sobre o botão, ele mudará a cor do primeiro plano de um botão. Quando o mouse sai do botão, ele volta à cor original.

Por que precisamos de propriedades de dependência

A propriedade de dependência oferece todos os tipos de benefícios quando você a usa em seu aplicativo. A propriedade de dependência pode ser usada em uma propriedade CLR nos seguintes cenários -

  • Se você deseja definir o estilo
  • Se você quiser vinculação de dados
  • Se você deseja definir com um recurso (um recurso estático ou dinâmico)
  • Se você quiser apoiar animação

Basicamente, as Propriedades de dependência oferecem muitas funcionalidades que você não obterá usando uma propriedade CLR.

A principal diferença entre dependency properties e outro CLR properties estão listados abaixo -

  • As propriedades CLR podem ler / gravar diretamente do membro privado de uma classe usando getter e setter. Em contraste, as propriedades de dependência não são armazenadas no objeto local.

  • As propriedades de dependência são armazenadas em um dicionário de pares de chave / valor que é fornecido pela classe DependencyObject. Ele também economiza muita memória porque armazena a propriedade quando alterada. Ele também pode ser vinculado a XAML.

Propriedades de dependência personalizadas

No .NET framework, as propriedades de dependência personalizadas também podem ser definidas. Siga as etapas fornecidas a seguir para definir a propriedade de dependência personalizada em C #.

  • Declare e registre seu dependency property com registro de chamadas do sistema.

  • Proporciona a setter e getter para a propriedade.

  • Defina um static handler que irá lidar com quaisquer mudanças que ocorram globalmente

  • Defina um instance handler que tratará de quaisquer alterações que ocorram nessa instância específica.

O código C # a seguir define uma propriedade de dependência para definir o SetText propriedade do controle do usuário.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes;  

namespace WpfApplication3 { 
   /// <summary> 
      /// Interaction logic for UserControl1.xaml 
   /// </summary> 
	
   public partial class UserControl1 : UserControl { 
	
      public UserControl1() { 
         InitializeComponent(); 
      }
		
      public static readonly DependencyProperty SetTextProperty = 
         DependencyProperty.Register("SetText", typeof(string), typeof(UserControl1), new 
            PropertyMetadata("", new PropertyChangedCallback(OnSetTextChanged))); 
				
      public string SetText { 
         get { return (string)GetValue(SetTextProperty); } 
         set { SetValue(SetTextProperty, value); } 
      } 
		
      private static void OnSetTextChanged(DependencyObject d,
         DependencyPropertyChangedEventArgs e) { 
         UserControl1 UserControl1Control = d as UserControl1; 
         UserControl1Control.OnSetTextChanged(e); 
      } 
		
      private void OnSetTextChanged(DependencyPropertyChangedEventArgs e) { 
         tbTest.Text = e.NewValue.ToString(); 
      }  
   } 
}

Aqui está o arquivo XAML no qual o TextBlock é definido como um controle de usuário e a propriedade Text será atribuída a ele pela propriedade de dependência SetText.

O código XAML a seguir cria um controle de usuário e inicializa seu SetText propriedade de dependência.

<Window x:Class = "WpfApplication3.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:views = "clr-namespace:WpfApplication3"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <views:UserControl1 SetText = "Hellow World"/> 
   </Grid> 
	
</Window>

Vamos rodar este aplicativo. Você pode observar imediatamente que em nossa MainWindow, a propriedade de dependência para controle de usuário foi usada com sucesso como um Texto.

UMA routed eventé um tipo de evento que pode invocar manipuladores em vários ouvintes em uma árvore de elementos, em vez de apenas o objeto que gerou o evento. É basicamente um evento CLR com suporte por uma instância da classe Routed Event. Ele é registrado no sistema de eventos WPF. RoutedEvents têm três estratégias de roteamento principais que são as seguintes -

  • Evento Direto
  • Evento Borbulhante
  • Evento Túnel

Evento Direto

Um evento direto é semelhante a eventos em formulários do Windows que são gerados pelo elemento no qual o evento é originado.

Ao contrário de um evento CLR padrão, os eventos roteados diretos suportam o tratamento de classes e podem ser usados ​​em Event Setters e Event Triggers dentro do seu estilo de controle personalizado.

Um bom exemplo de um evento direto seria o evento MouseEnter.

Evento Borbulhante

Um evento bubbling começa com o elemento onde o evento é originado. Em seguida, ele sobe na árvore visual até o elemento superior da árvore visual. Portanto, no WPF, o elemento superior é provavelmente uma janela.

Evento Túnel

Os manipuladores de eventos na raiz da árvore de elementos são chamados e, em seguida, o evento desce pela árvore visual para todos os nós filhos até atingir o elemento no qual o evento se originou.

A diferença entre um evento bubbling e um tunneling é que um evento tunneling sempre começará com uma visualização.

Em um aplicativo WPF, os eventos são geralmente implementados como um par tunelamento / borbulhamento. Portanto, você terá uma visualização do MouseDown e, em seguida, um evento MouseDown.

A seguir, é fornecido um exemplo simples de um evento roteado no qual um botão e três blocos de texto são criados com algumas propriedades e eventos.

<Window x:Class = "WPFRoutedEvents.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click  = "Window_Click" >
	
   <Grid> 
      <StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click">
		
         <StackPanel Margin = "10"> 
            <TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1" /> 
            <TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2" /> 
            <TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3" /> 
         </StackPanel> 
			
         <Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/> 
      </StackPanel> 
   </Grid> 
	
</Window>

Aqui está o código C # para a implementação de eventos Click para Button, StackPanel e Window.

using System.Windows; 
 
namespace WPFRoutedEvents { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary>
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void Button_Click(object sender, RoutedEventArgs e) { 
         txt1.Text = "Button is Clicked"; 
      } 
		
      private void StackPanel_Click(object sender, RoutedEventArgs e) { 
         txt2.Text = "Click event is bubbled to Stack Panel"; 
      } 
		
      private void Window_Click(object sender, RoutedEventArgs e) { 
         txt3.Text = "Click event is bubbled to Window"; 
      }
		
   } 
}

Quando você compila e executa o código acima, ele irá produzir a seguinte janela -

Ao clicar no botão, os blocos de texto serão atualizados, conforme mostrado abaixo.

Se você quiser interromper o evento roteado em qualquer nível específico, será necessário definir o e.Handled = true;

Vamos mudar o StackPanel_Click evento como mostrado abaixo -

private void StackPanel_Click(object sender, RoutedEventArgs e) { 
   txt2.Text = "Click event is bubbled to Stack Panel"; 
   e.Handled = true; 
}

Ao clicar no botão, você observará que o evento de clique não será roteado para a janela e irá parar no painel de pilha e o bloco de texto não será atualizado.

Eventos roteados personalizados

Na estrutura .NET, o evento roteado personalizado também pode ser definido. Você precisa seguir as etapas fornecidas a seguir para definir um evento roteado personalizado em C #.

  • Declare e registre seu evento roteado com a chamada de sistema RegisterRoutedEvent.

  • Especifique a estratégia de roteamento, ou seja, bolha, túnel ou direto.

  • Fornece o manipulador de eventos.

Vamos dar um exemplo para entender mais sobre eventos roteados personalizados. Siga as etapas abaixo -

  • Crie um novo projeto WPF com WPFCustomRoutedEvent

  • Clique com o botão direito na sua solução e selecione Adicionar> Novo Item ...

  • A seguinte caixa de diálogo será aberta, agora selecione Custom Control (WPF) e nomeá-lo MyCustomControl.

  • Clique no Add e você verá que dois novos arquivos (Themes / Generic.xaml e MyCustomControl.cs) serão adicionados à sua solução.

O código XAML a seguir define o estilo do controle personalizado no arquivo Generic.xaml.

<ResourceDictionary 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent">
	
   <Style TargetType = "{x:Type local:MyCustomControl}"> 
      <Setter Property = "Margin" Value = "50"/> 
      <Setter Property = "Template"> 
         <Setter.Value> 
            <ControlTemplate TargetType = "{x:Type local:MyCustomControl}">
				
               <Border Background = "{TemplateBinding Background}" 
                  BorderBrush = "{TemplateBinding BorderBrush}" 
                  BorderThickness = "{TemplateBinding BorderThickness}"> 
                  <Button x:Name = "PART_Button" Content = "Click Me" /> 
               </Border> 
					
            </ControlTemplate> 
         </Setter.Value> 
      </Setter> 
   </Style> 
	
</ResourceDictionary>

A seguir está o código C # para o MyCustomControl class que herda do Control class em que um Click de evento roteado personalizado é criado para o controle personalizado.

using System.Windows; 
using System.Windows.Controls;  

namespace WPFCustomRoutedEvent { 

   public class MyCustomControl : Control { 
	
      static MyCustomControl() { 
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), 
            new FrameworkPropertyMetadata(typeof(MyCustomControl))); 
      } 
		
      public override void OnApplyTemplate() { 
         base.OnApplyTemplate();
			
         //demo purpose only, check for previous instances and remove the handler first 
         var button  =  GetTemplateChild("PART_Button") as Button; 
         if (button ! =  null) 
         button.Click + =  Button_Click;  
      } 
		
      void Button_Click(object sender, RoutedEventArgs e) { 
         RaiseClickEvent(); 
      } 
		
      public static readonly RoutedEvent ClickEvent  =  
         EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, 
         typeof(RoutedEventHandler), typeof(MyCustomControl)); 
			
      public event RoutedEventHandler Click { 
         add { AddHandler(ClickEvent, value); } 
         remove { RemoveHandler(ClickEvent, value); } 
      } 
		
      protected virtual void RaiseClickEvent() { 
         RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent); 
         RaiseEvent(args); 
      }
		
   } 
}

Aqui está a implementação de evento roteado personalizado em C #, que exibirá uma caixa de mensagem quando o usuário clicar nela.

using System.Windows;  

namespace WPFCustomRoutedEvent { 
   // <summary> 
      // Interaction logic for MainWindow.xaml
   // </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void MyCustomControl_Click(object sender, RoutedEventArgs e) { 
         MessageBox.Show("It is the custom routed event of your custom control"); 
      } 
		
   } 
}

Aqui está a implementação em MainWindow.xaml para adicionar o controle personalizado com um evento roteado Click.

<Window x:Class = "WPFCustomRoutedEvent.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <local:MyCustomControl Click = "MyCustomControl_Click" /> 
   </Grid> 
	
</Window>

Quando o código acima for compilado e executado, ele produzirá a seguinte janela que contém um controle personalizado.

Quando você clica no controle personalizado, a seguinte mensagem é exibida.

O Windows Presentation Foundation (WPF) permite que os desenvolvedores criem e criem facilmente aplicativos baseados em interface do usuário visualmente enriquecidos.

  • Os elementos ou controles clássicos da IU em outras estruturas da IU também são aprimorados em aplicativos WPF.

  • Todos os controles WPF padrão podem ser encontrados na caixa de ferramentas, que faz parte do System.Windows.Controls.

  • Esses controles também podem ser criados na linguagem de marcação XAML.

A hierarquia de herança completa dos controles WPF são as seguintes -

A tabela a seguir contém uma lista de controles que discutiremos nos capítulos subsequentes.

Sr. Não. Controles e descrição
1 Botão

Um controle que responde à entrada do usuário

2 Calendário

Representa um controle que permite a um usuário selecionar uma data usando uma exibição de calendário visual.

3 CheckBox

Um controle que um usuário pode selecionar ou limpar.

4 Caixa combo

Uma lista suspensa de itens que um usuário pode selecionar.

5 Menu contextual

Obtém ou define o elemento do menu de contexto que deve aparecer sempre que o menu de contexto é solicitado por meio da interface do usuário (IU) de dentro desse elemento.

6 Grade de dados

Representa um controle que exibe dados em uma grade personalizável.

7 DatePicker

Um controle que permite ao usuário selecionar uma data.

8 Diálogos

Um aplicativo também pode exibir janelas adicionais para ajudar o usuário a reunir ou exibir informações importantes.

9 GridView

Um controle que apresenta uma coleção de itens em linhas e colunas que podem rolar horizontalmente.

10 Imagem

Um controle que apresenta uma imagem.

11 Rótulo

Exibe texto em um formulário. Fornece suporte para chaves de acesso.

12 ListBox

Um controle que apresenta uma lista embutida de itens que o usuário pode selecionar.

13 Menus

Representa um controle de menu do Windows que permite organizar hierarquicamente elementos associados a comandos e manipuladores de eventos.

14 PasswordBox

Um controle para inserir senhas.

15 Aparecer

Exibe o conteúdo acima do conteúdo existente, dentro dos limites da janela do aplicativo.

16 Barra de progresso

Um controle que indica o progresso exibindo uma barra.

17 Botao de radio

Um controle que permite ao usuário selecionar uma única opção de um grupo de opções.

18 ScrollViewer

Um controle de contêiner que permite ao usuário deslocar e aplicar zoom em seu conteúdo.

19 Slider

Um controle que permite ao usuário selecionar a partir de uma gama de valores movendo um controle Thumb ao longo de uma trilha.

20 TextBlock

Um controle que exibe texto.

21 ToggleButton

Um botão que pode ser alternado entre 2 estados.

22 Dica de ferramenta

Uma janela pop-up que exibe informações sobre um elemento.

23 Janela

A janela raiz que fornece a opção de minimizar / maximizar, barra de título, borda e botão Fechar

24 Controles de terceiros

Use controles de terceiros em seus aplicativos WPF.

Discutiremos todos esses controles um por um com sua implementação.

O layout dos controles é muito importante e crítico para a usabilidade do aplicativo. É usado para organizar um grupo de elementos GUI em seu aplicativo. Existem certas coisas importantes a considerar ao selecionar os painéis de layout -

  • Posições dos elementos filhos
  • Tamanhos dos elementos filhos
  • Sobreposição de elementos filho sobrepostos uns sobre os outros

A disposição fixa dos controles em pixels não funciona quando o aplicativo deve ser colocado em diferentes resoluções de tela. O XAML fornece um rico conjunto de painéis de layout integrados para organizar os elementos da GUI de maneira apropriada. Alguns dos painéis de layout mais comumente usados ​​e populares são os seguintes -

Sr. Não. Painéis e descrição
1 Stack Panel

O painel de pilha é um painel de layout simples e útil em XAML. No painel de pilha, os elementos filho podem ser organizados em uma única linha, horizontal ou verticalmente, com base na propriedade de orientação.

2 Painel de envoltório

Em WrapPanel, os elementos filho são posicionados em ordem sequencial, da esquerda para a direita ou de cima para baixo com base na propriedade de orientação.

3 Painel Dock

DockPanel define uma área para organizar os elementos filhos em relação uns aos outros, horizontal ou verticalmente. Com o DockPanel, você pode facilmente encaixar elementos-filho na parte superior, inferior, direita, esquerda e central usando oDock propriedade.

4 Painel de Tela

O painel de tela é o painel de layout básico no qual os elementos filho podem ser posicionados explicitamente usando coordenadas que são relativas ao Canvas qualquer lado, como esquerdo, direito, superior e inferior.

5 Painel de grade

Um painel de grade fornece uma área flexível que consiste em linhas e colunas. Em uma grade, os elementos filhos podem ser organizados em forma tabular.

O aninhamento de layout significa usar o painel de layout dentro de outro layout, por exemplo, definir painéis de pilha dentro de uma grade. Esse conceito é amplamente utilizado para aproveitar as vantagens de vários layouts em um aplicativo. No exemplo a seguir, usaremos painéis de pilha dentro de uma grade.

Vamos dar uma olhada no seguinte código XAML.

<Window x:Class = "WPFNestingLayouts.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFNestingLayouts" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid Background = "AntiqueWhite"> 
      <Grid.RowDefinitions> 
         <RowDefinition Height = "*" /> 
         <RowDefinition Height = "*" /> 
         <RowDefinition Height = "*" /> 
         <RowDefinition Height = "*" /> 
         <RowDefinition Height = "*" /> 
      </Grid.RowDefinitions> 
		
      <Grid.ColumnDefinitions> 
         <ColumnDefinition Width = "*" /> 
      </Grid.ColumnDefinitions> 
		
      <Label Content = "Employee Info" FontSize = "15"
         FontWeight = "Bold" Grid.Column = "0" Grid.Row = "0"/> 
			
      <StackPanel Grid.Column = "0" Grid.Row = "1" Orientation = "Horizontal"> 
         <Label Content = "Name"  VerticalAlignment = "Center" Width = "70"/> 
         <TextBox Name = "txtName" Text = "Muhammad Ali" VerticalAlignment = "Center"
            Width = "200">
         </TextBox> 
      </StackPanel>
		
      <StackPanel Grid.Column = "0" Grid.Row = "2" Orientation = "Horizontal"> 
         <Label Content = "ID" VerticalAlignment = "Center" Width = "70"/> 
         <TextBox Name = "txtCity" Text = "421" VerticalAlignment = "Center"
            Width = "50">
         </TextBox> 
      </StackPanel>
		
      <StackPanel Grid.Column = "0" Grid.Row = "3" Orientation = "Horizontal"> 
         <Label Content = "Age" VerticalAlignment = "Center" Width = "70"/> 
         <TextBox Name = "txtState" Text = "32" VerticalAlignment = "Center"
            Width = "50"></TextBox> 
      </StackPanel> 
		
      <StackPanel Grid.Column = "0" Grid.Row = "4" Orientation = "Horizontal"> 
         <Label Content = "Title" VerticalAlignment = "Center" Width = "70"/> 
         <TextBox Name = "txtCountry" Text = "Programmer" VerticalAlignment = "Center"
            Width = "200"></TextBox> 
      </StackPanel> 
		
   </Grid> 
	
</Window>

Quando você compila e executa o código acima, ele produzirá a seguinte janela.

Recomendamos que você execute o código de exemplo acima e tente outros layouts de aninhamento.

O Windows Presentation Foundation (WPF) fornece uma API poderosa com a ajuda da qual os aplicativos podem obter entrada de vários dispositivos, como mouse, teclado e painéis de toque. Neste capítulo, discutiremos os seguintes tipos de entrada que podem ser manipulados em aplicativos WPF -

Sr. Não. Entradas e descrição
1 Rato

Existem diferentes tipos de entradas de mouse, como MouseDown, MouseEnter, MouseLeave, etc.

2 Teclado

Existem muitos tipos de entradas de teclado, como KeyDown, KeyUp, TextInput, etc.

3 ContextMenu ou RoutedCommands

RoutedCommands permite o tratamento de entrada em um nível mais semântico. Na verdade, essas são instruções simples como Novo, Abrir, Copiar, Recortar e Salvar.

4 Multi Touch

O Windows 7 e suas versões superiores têm a capacidade de receber entrada de vários dispositivos sensíveis ao toque. Os aplicativos WPF também podem manipular a entrada de toque como outra entrada, como o mouse ou teclado, gerando eventos quando ocorre um toque.

O argumento da linha de comando é um mecanismo onde um usuário pode passar um conjunto de parâmetros ou valores para um aplicativo WPF quando ele é executado. Esses argumentos são muito importantes para controlar um aplicativo de fora, por exemplo, se você deseja abrir um documento do Word a partir do prompt de comando, você pode usar este comando “C:\> start winword word1.docx”E vai abrir word1.docx documento.

Os argumentos da linha de comando são tratados na função de inicialização. A seguir está um exemplo simples que mostra como passar argumentos de linha de comando para um aplicativo WPF. Vamos criar um novo aplicativo WPF com o nomeWPFCommandLine.

  • Arraste uma caixa de texto da caixa de ferramentas para a janela de design.

  • Neste exemplo, passaremos um caminho de arquivo txt para nosso aplicativo como parâmetro de linha de comando.

  • O programa lerá o arquivo txt e escreverá todo o texto na caixa de texto.

  • O código XAML a seguir cria uma caixa de texto e a inicializa com algumas propriedades.

<Window x:Class = "WPFCommandLine.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFCommandLine" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid> 
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"  
         Height = "180" Margin = "100" TextWrapping = "Wrap" 
         VerticalAlignment = "Top" Width = "300"/> 
   </Grid> 
	
</Window>
  • Agora, inscreva-se no evento Startup no arquivo App.xaml conforme mostrado abaixo.
<Application x:Class = "WPFCommandLine.App" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:local = "clr-namespace:WPFCommandLine" 
   StartupUri = "MainWindow.xaml" Startup = "app_Startup"> 
	
   <Application.Resources> 
          
   </Application.Resources>
	
</Application>
  • A seguir está a implementação do evento app_Startup em App.xaml.cs que obterá os argumentos da linha de comando.

using System.Windows;
  
namespace WPFCommandLine { 
   /// <summary> 
      /// Interaction logic for App.xaml 
   /// </summary> 
	
   public partial class App : Application { 
      public static string[] Args;
		
      void app_Startup(object sender, StartupEventArgs e) { 
         // If no command line arguments were provided, don't process them 
         if (e.Args.Length == 0) return;
			
         if (e.Args.Length > 0) { 
            Args = e.Args; 
         } 
      } 
   } 
}
  • Agora, na classe MainWindow, o programa irá abrir o arquivo txt e escrever todo o texto na caixa de texto.

  • Se algum erro for encontrado, o programa exibirá uma mensagem de erro na caixa de texto.

using System; 
using System.IO; 
using System.Windows;  

namespace WPFCommandLine { 

   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         String[] args = App.Args;
			
         try {
            // Open the text file using a stream reader. 
            using (StreamReader sr = new StreamReader(args[0])) { 
               // Read the stream to a string, and write  
               // the string to the text box 
               String line = sr.ReadToEnd(); 
               textBox.AppendText(line.ToString()); 
               textBox.AppendText("\n"); 
            } 
         } 
         catch (Exception e) { 
            textBox.AppendText("The file could not be read:"); 
            textBox.AppendText("\n"); 
            textBox.AppendText(e.Message); 
         } 
      } 
   } 
}
  • Quando o código acima é compilado e executado, ele produzirá uma janela em branco com uma caixa de texto porque este programa precisa de um argumento de linha de comando. Portanto, o Visual Studio fornece uma maneira fácil de executar seu aplicativo com parâmetros de linha de comando.

  • Clique com o botão direito do mouse em seu projeto WPF no explorador de soluções e selecione propriedades; a janela a seguir será exibida.

  • Selecione a opção Debug e escreva o caminho do arquivo no argumento da linha de comando.

  • Crie um arquivo txt com Test.txt e escreva algum texto nesse arquivo e salve-o em qualquer local. Neste caso, o arquivo txt é salvo em “D:\" disco rígido.

  • Salve as alterações em seu projeto, compile e execute seu aplicativo agora. Você verá o texto em TextBox que o programa lê do arquivo Text.txt.

Agora vamos tentar mudar o nome do arquivo em sua máquina de Test.txt para Test1.txt e execute seu programa novamente, então você verá aquela mensagem de erro na caixa de texto.

Recomendamos que você execute o código acima e siga todas as etapas para executar seu aplicativo com sucesso.

A vinculação de dados é um mecanismo em aplicativos WPF que fornece uma maneira simples e fácil para os aplicativos do Windows Runtime exibir e interagir com os dados. Nesse mecanismo, o gerenciamento de dados é totalmente separado da forma de dados.

A vinculação de dados permite o fluxo de dados entre os elementos da IU e o objeto de dados na interface do usuário. Quando uma ligação é estabelecida e os dados ou seu modelo de negócios são alterados, ele reflete as atualizações automaticamente para os elementos da IU e vice-versa. Também é possível vincular, não a uma fonte de dados padrão, mas a outro elemento na página.

A vinculação de dados é de dois tipos - one-way data binding e two-way data binding.

Vinculação de dados unilateral

Na vinculação unilateral, os dados são vinculados de sua origem (ou seja, o objeto que contém os dados) ao seu destino (ou seja, o objeto que exibe os dados)

  • Vamos dar um exemplo simples para entender a vinculação de dados unilateral em detalhes. Em primeiro lugar, crie um novo projeto WPF com o nomeWPFDataBinding.

  • O código XAML a seguir cria dois rótulos, duas caixas de texto e um botão e os inicializa com algumas propriedades.

<Window x:Class = "WPFDataBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFDataBinding" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
	
      <Grid.RowDefinitions> 
         <RowDefinition Height = "Auto" /> 
         <RowDefinition Height = "Auto" /> 
         <RowDefinition Height = "*" /> 
      </Grid.RowDefinitions> 
		
      <Grid.ColumnDefinitions> 
         <ColumnDefinition Width = "Auto" /> 
         <ColumnDefinition Width = "200" /> 
      </Grid.ColumnDefinitions>
		
      <Label Name = "nameLabel" Margin = "2">_Name:</Label> 
		
      <TextBox Name = "nameText" Grid.Column = "1" Margin = "2" 
         Text = "{Binding Name, Mode = OneWay}"/>  
			
      <Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label> 
		
      <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2" 
         Text = "{Binding Age, Mode = OneWay}"/>  
			
      <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2"> 
         <Button Content = "_Show..." Click="Button_Click" /> 
      </StackPanel> 
		
   </Grid> 
</Window>
  • As propriedades de texto de ambas as caixas de texto vinculam-se a “Nome” e “Idade”, que são variáveis ​​de classe da classe Person que é mostrada abaixo.

  • Na classe Person, temos apenas duas variáveis Name e Age, e seu objeto é inicializado em MainWindow classe.

  • No código XAML, estamos vinculando a uma propriedade Name e Age, mas não selecionamos a qual objeto essa propriedade pertence.

  • A maneira mais fácil é atribuir um objeto a DataContext cujas propriedades estamos vinculando no seguinte código C # em MainWindowconstructor.

using System.Windows;  
namespace WPFDataBinding { 

   public partial class MainWindow : Window {
	
      Person person = new Person { Name = "Salman", Age = 26 };
		
      public MainWindow() { 
         InitializeComponent(); 
         this.DataContext = person; 
      } 
		
      private void Button_Click(object sender, RoutedEventArgs e) { 
         string message = person.Name + " is " + person.Age; 
         MessageBox.Show(message); 
      } 
   } 
	
   public class Person { 
	
      private string nameValue;
		
      public string Name { 
         get { return nameValue; } 
         set { nameValue = value; } 
      } 
		
      private double ageValue; 
		
      public double Age { 
         get { return ageValue; } 
				
         set { 
            if (value != ageValue) { 
               ageValue = value; 
            } 
         } 
      }
		
   } 
}
  • Vamos executar este aplicativo e você poderá ver imediatamente em nossa MainWindow que vinculamos com êxito ao Nome e à Idade desse objeto Pessoa.

Quando você pressiona o Show botão, ele exibirá o nome e a idade na caixa de mensagem.

Vamos mudar o nome e a idade na caixa de diálogo.

Se você clicar no botão Mostrar, ele exibirá novamente a mesma mensagem.

Isso porque o modo de vinculação de dados é definido como unilateral no código XAML. Para mostrar os dados atualizados, você precisará entender a vinculação de dados bidirecional.

Vinculação de dados bidirecional

Na ligação bidirecional, o usuário pode modificar os dados por meio da interface do usuário e ter esses dados atualizados na fonte. Se a fonte mudar enquanto o usuário estiver olhando para a visualização, você deseja que a visualização seja atualizada.

Vamos pegar o mesmo exemplo, mas aqui, vamos alterar o modo de vinculação de One Way para Two Way no código XAML.

<Window x:Class = "WPFDataBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFDataBinding" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
	
      <Grid.RowDefinitions> 
         <RowDefinition Height = "Auto" /> 
         <RowDefinition Height = "Auto" /> 
         <RowDefinition Height = "*" /> 
      </Grid.RowDefinitions> 
		
      <Grid.ColumnDefinitions> 
         <ColumnDefinition Width = "Auto" /> 
         <ColumnDefinition Width = "200" /> 
      </Grid.ColumnDefinitions> 
		
      <Label Name = "nameLabel" Margin = "2">_Name:</Label> 
      <TextBox Name = "nameText" Grid.Column = "1" Margin = "2" 
         Text = "{Binding Name, Mode = TwoWay}"/>  
      <Label Name = "ageLabel" Margin = "2" Grid.Row = "1">_Age:</Label> 
      <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "2" 
         Text = "{Binding Age, Mode = TwoWay}"/> 
			
      <StackPanel Grid.Row = "2" Grid.ColumnSpan = "2"> 
         <Button Content = "_Show..." Click = "Button_Click" /> 
      </StackPanel>
		
   </Grid>
	
</Window>

Vamos executar este aplicativo novamente.

Ele produzirá a mesma saída -

Vamos agora alterar os valores de Nome e Idade -

Se você clicar no botão Mostrar agora, ele exibirá a mensagem atualizada.

Recomendamos que você execute o código acima com ambos os casos para uma melhor compreensão do conceito.

Os recursos são normalmente definições conectadas a algum objeto que você antecipa usar mais de uma vez. É a capacidade de armazenar dados localmente para controles ou para a janela atual ou globalmente para todos os aplicativos.

Definir um objeto como recurso nos permite acessá-lo de outro lugar. O que significa é que o objeto pode ser reutilizado. Os recursos são definidos em dicionários de recursos e qualquer objeto pode ser definido como um recurso, tornando-o efetivamente um ativo compartilhável. Uma chave exclusiva é especificada para um recurso XAML e com essa chave, ela pode ser referenciada usando uma extensão de marcação StaticResource.

Os recursos podem ser de dois tipos -

  • StaticResource
  • DynamicResource

Um StaticResource é uma pesquisa única, enquanto um DynamicResource funciona mais como uma vinculação de dados. Ele lembra que uma propriedade está associada a uma chave de recurso específica. Se o objeto associado a essa chave mudar, o recurso dinâmico atualizará a propriedade de destino.

Exemplo

Aqui está um aplicativo simples para o recurso SolidColorBrush.

  • Vamos criar um novo projeto WPF com o nome WPFResouces.

  • Arraste dois retângulos e defina suas propriedades conforme mostrado no código XAML a seguir.

<Window x:Class = "WPFResources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFResources" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Window.Resources> 
      <SolidColorBrush x:Key = "brushResource" Color = "Blue" /> 
   </Window.Resources> 
	
   <StackPanel> 
      <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}" /> 
      <Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}" /> 
      <Button x:Name = "changeResourceButton"
         Content = "_Change Resource" Click = "changeResourceButton_Click" /> 
   </StackPanel> 
	
</Window>
  • No código XAML acima, você pode ver que um retângulo tem StaticResource e o outro tem DynamicResource e a cor de brushResource é Bisque.

  • Quando você compila e executa o código, ele produzirá a seguinte MainWindow.

Ao clicar no botão "Alterar recurso", você verá que o retângulo com DynamicResource mudará sua cor para vermelho.

Escopo do Recurso

Os recursos são definidos em resource dictionaries, mas existem vários lugares onde um dicionário de recursos pode ser definido. No exemplo acima, um dicionário de recursos é definido no nível da janela / página. Em qual dicionário um recurso é definido limita imediatamente o escopo desse recurso. Portanto, o escopo, ou seja, onde você pode usar o recurso, depende de onde você o definiu.

  • Defina o recurso no dicionário de recursos de uma grade e ele é acessível apenas por aquela grade e por seus elementos filhos.

  • Defina-o em uma janela / página e é acessível por todos os elementos dessa janela / página.

  • A raiz do aplicativo pode ser encontrada no dicionário de recursos App.xaml. É a raiz de nosso aplicativo, portanto, os recursos definidos aqui têm como escopo todo o aplicativo.

No que diz respeito ao escopo do recurso, os mais frequentemente são o nível do aplicativo, o nível da página e um nível de elemento específico, como uma grade, StackPanel etc.

O aplicativo acima possui recursos em seu nível de janela / página.

Dicionários de recursos

Dicionários de recursos em aplicativos XAML implicam que os dicionários de recursos são mantidos em arquivos separados. Ele é seguido em quase todos os aplicativos XAML. Definir recursos em arquivos separados pode ter as seguintes vantagens -

  • Separação entre definir recursos no dicionário de recursos e o código relacionado à IU.

  • Definir todos os recursos em um arquivo separado, como App.xaml, os tornaria disponíveis no aplicativo.

Então, como definimos nossos recursos em um dicionário de recursos em um arquivo separado? Bem, é muito fácil, basta adicionar um novo dicionário de recursos por meio do Visual Studio seguindo as etapas fornecidas abaixo -

  • Em sua solução, adicione uma nova pasta e nomeie-a ResourceDictionaries.

  • Clique com o botão direito nesta pasta e selecione Dicionário de Recursos em Adicionar item de submenu e nomeie-o DictionaryWithBrush.xaml

Exemplo

Agora vamos dar o mesmo exemplo, mas aqui definiremos o dicionário de recursos no nível do aplicativo. O código XAML para MainWindow.xaml é o seguinte -

<Window x:Class = "WPFResources.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFResources" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <StackPanel> 
      <Rectangle Height = "50" Margin = "20" Fill = "{StaticResource brushResource}" /> 
      <Rectangle Height = "50" Margin = "20" Fill = "{DynamicResource brushResource}" /> 
      <Button x:Name = "changeResourceButton"
         Content = "_Change Resource" Click = "changeResourceButton_Click" /> 
   </StackPanel> 
	
</Window>

Aqui está a implementação em DictionaryWithBrush.xaml -

<ResourceDictionary xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"> 
   <SolidColorBrush x:Key = "brushResource" Color = "Blue" /> 
</ResourceDictionary>

Aqui está a implementação em app.xaml -

<Application x:Class="WPFResources.App" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   StartupUri = "MainWindow.xaml"> 
	
   <Application.Resources> 
      <ResourceDictionary Source = " XAMLResources\ResourceDictionaries\DictionaryWithBrush.xaml"/> 
   </Application.Resources> 
	
</Application>

Quando o código acima for compilado e executado, ele produzirá a seguinte saída -

Quando você clica no botão Alterar Recurso, o retângulo muda sua cor para Vermelho.

Recomendamos que você execute o código acima e tente mais alguns recursos (por exemplo, cor de fundo).

Um modelo descreve a aparência geral e a aparência visual de um controle. Para cada controle, há um modelo padrão associado a ele que dá ao controle sua aparência. Em aplicativos WPF, você pode criar facilmente seus próprios modelos quando quiser personalizar o comportamento visual e a aparência visual de um controle.

A conectividade entre a lógica e o modelo pode ser alcançada por vinculação de dados. A principal diferença entrestyles e templates estão listados abaixo -

  • Os estilos só podem alterar a aparência do seu controle com as propriedades padrão desse controle.

  • Com os modelos, você pode acessar mais partes de um controle do que estilos. Você também pode especificar o comportamento existente e o novo de um controle.

Existem dois tipos de modelos que são mais comumente usados ​​-

  • Modelo de controle
  • Modelo de Dados

Modelo de controle

O modelo de controle define a aparência visual de um controle. Todos os elementos da IU têm algum tipo de aparência e comportamento, por exemplo, Button tem aparência e comportamento. O evento de clique ou o evento de passar o mouse são os comportamentos disparados em resposta a um clique e ao passar o mouse e também há uma aparência padrão do botão que pode ser alterado pelo modelo de controle.

Exemplo

Vamos dar um exemplo simples. Vamos criar dois botões (um é com o modelo e o outro é o botão padrão) e inicializá-los com algumas propriedades.

<Window x:Class = "TemplateDemo.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Window.Resources> 
      <ControlTemplate x:Key = "ButtonTemplate" TargetType = "Button">
		
         <Grid> 
            <Ellipse x:Name = "ButtonEllipse" Height = "100" Width = "150" > 
               <Ellipse.Fill> 
                  <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4"> 
                     <GradientStop Offset = "0" Color = "Red" /> 
                     <GradientStop Offset = "1" Color = "Orange" /> 
                  </LinearGradientBrush> 
               </Ellipse.Fill> 
            </Ellipse> 
				
            <ContentPresenter Content = "{TemplateBinding Content}" 
               HorizontalAlignment = "Center" VerticalAlignment = "Center" /> 
         </Grid> 
			
         <ControlTemplate.Triggers> 
			
            <Trigger Property = "IsMouseOver" Value = "True"> 
               <Setter TargetName = "ButtonEllipse" Property = "Fill" > 
                  <Setter.Value> 
                     <LinearGradientBrush StartPoint = "0,0.2" EndPoint = "0.2,1.4"> 
                        <GradientStop Offset = "0" Color = "YellowGreen" /> 
                        <GradientStop Offset = "1" Color = "Gold" /> 
                     </LinearGradientBrush> 
                  </Setter.Value> 
               </Setter> 
            </Trigger> 
				
            <Trigger Property = "IsPressed" Value = "True"> 
               <Setter Property = "RenderTransform"> 
                  <Setter.Value> 
                     <ScaleTransform ScaleX = "0.8" ScaleY = "0.8" 
                        CenterX = "0" CenterY = "0"  /> 
                  </Setter.Value> 
               </Setter> 
               <Setter Property = "RenderTransformOrigin" Value = "0.5,0.5" /> 
            </Trigger> 
				
         </ControlTemplate.Triggers> 
			
      </ControlTemplate> 
   </Window.Resources> 
	
   <StackPanel> 
      <Button Content = "Round Button!"
         Template = "{StaticResource ButtonTemplate}" 
         Width = "150" Margin = "50" /> 
      <Button Content = "Default Button!" Height = "40" 
         Width = "150" Margin = "5" />
   </StackPanel> 
	
</Window>

Quando você compila e executa o código acima, ele exibe a seguinte MainWindow.

Quando você move o mouse sobre o botão com o modelo personalizado, ele muda de cor conforme mostrado abaixo.

Modelo de Dados

Um modelo de dados define e especifica a aparência e a estrutura de uma coleção de dados. Ele fornece a flexibilidade de formatar e definir a apresentação dos dados em qualquer elemento da IU. É usado principalmente em controles de item relacionados a dados, como ComboBox, ListBox, etc.

Exemplo

  • Vamos dar um exemplo simples para entender o conceito de modelo de dados. Crie um novo projeto WPF com o nomeWPFDataTemplates.

  • No código XAML a seguir, criaremos um modelo de dados como recurso para conter rótulos e caixas de texto. Há um botão e uma caixa de listagem para exibir os dados.

<Window x:Class = "WPFDataTemplates.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFDataTemplates" 
   xmlns:loc = "clr-namespace:WPFDataTemplates" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Window.Resources> 
      <DataTemplate DataType = "{x:Type loc:Person}"> 
		
         <Grid> 
            <Grid.RowDefinitions> 
               <RowDefinition Height = "Auto" /> 
               <RowDefinition Height = "Auto" /> 
            </Grid.RowDefinitions> 
				
            <Grid.ColumnDefinitions> 
               <ColumnDefinition Width = "Auto" /> 
               <ColumnDefinition Width = "200" /> 
            </Grid.ColumnDefinitions>
				
            <Label Name = "nameLabel" Margin = "10"/> 
            <TextBox Name = "nameText" Grid.Column = "1" Margin = "10" 
               Text = "{Binding Name}"/>  
            <Label Name = "ageLabel" Margin = "10" Grid.Row = "1"/> 
            <TextBox Name = "ageText" Grid.Column = "1" Grid.Row = "1" Margin = "10" 
               Text = "{Binding Age}"/> 
         </Grid> 
			
      </DataTemplate> 
   </Window.Resources> 
	
   <Grid> 
      <Grid.RowDefinitions> 
         <RowDefinition Height = "Auto" /> 
         <RowDefinition Height = "*" /> 
      </Grid.RowDefinitions> 
		
      <ListBox ItemsSource = "{Binding}" />  
      <StackPanel Grid.Row = "1" > 
         <Button Content = "_Show..." Click = "Button_Click" Width = "80" HorizontalAlignment = "Left" Margin = "10"/> 
      </StackPanel> 
		
   </Grid> 
	
</Window>

Aqui está implementation in C# em que uma lista de objetos Person são atribuídos a DataContext, implementação da classe Person e evento de clique de botão.

using System.Collections.Generic; 
using System.Windows;
  
namespace WPFDataTemplates { 

   public partial class MainWindow : Window { 
	
      Person src = new Person { Name = "Ali", Age = 27 }; 
      List<Person> people = new List<Person>(); 
		
      public MainWindow() { 
         InitializeComponent(); 
         people.Add(src); 
         people.Add(new Person { Name = "Mike", Age = 62 }); 
         people.Add(new Person { Name = "Brian", Age = 12 });  
         this.DataContext = people; 
      } 
		
      private void Button_Click(object sender, RoutedEventArgs e) { 
         string message = src.Name + " is " + src.Age; 
         MessageBox.Show(message); 
      } 
   } 
	
   public class Person { 
      private string nameValue; 
		
      public string Name { 
         get { return nameValue; } 
         set { nameValue = value; } 
      }  
		
      private double ageValue; 
		
      public double Age { 
         get { return ageValue; } 
         set { 
            if (value != ageValue) { 
            ageValue = value; 
            } 
         } 
      } 
   } 
	
}

Quando você compila e executa o código acima, ele produzirá a seguinte janela. Ele contém uma lista e, dentro da caixa de listagem, cada item da caixa de listagem contém os dados do objeto da classe Person que são exibidos nas caixas Rótulos e Texto.

A estrutura .NET fornece várias estratégias para personalizar e personalizar a aparência de um aplicativo. Os estilos nos fornecem a flexibilidade de definir algumas propriedades de um objeto e reutilizar essas configurações específicas em vários objetos para uma aparência consistente.

  • Em estilos, você pode definir apenas as propriedades existentes de um objeto, como Altura, Largura, Tamanho da fonte, etc.

  • Apenas o comportamento padrão de um controle pode ser especificado.

  • Várias propriedades podem ser adicionadas em um único estilo.

Os estilos são usados ​​para dar uma aparência uniforme a um conjunto de controles. Os estilos implícitos são usados ​​para aplicar uma aparência a todos os controles de um determinado tipo e simplificar o aplicativo. Imagine três botões, todos eles devem ter a mesma aparência, mesma largura e altura, mesmo tamanho de fonte, mesma cor de primeiro plano, etc. Podemos definir todas essas propriedades nos próprios elementos do botão e isso ainda está bem para todos os botões. Dê uma olhada no diagrama a seguir.

Mas em aplicativos da vida real, você normalmente terá muito mais desses que precisam ser exatamente iguais. E não apenas botões, é claro, você normalmente deseja que seus blocos de texto, caixas de texto e caixas de combinação etc. tenham a mesma aparência em seu aplicativo. Certamente, deve haver uma maneira melhor de conseguir isso e é conhecido comostyling. Você pode pensar em um estilo como uma maneira conveniente de aplicar um conjunto de valores de propriedade a mais de um elemento. Dê uma olhada no diagrama a seguir.

Exemplo

Vamos dar um exemplo simples para entender esse conceito. Comece criando um novo projeto WPF.

  • Arraste três botões da caixa de ferramentas para a janela de design.

  • O código XAML a seguir cria três botões e os inicializa com algumas propriedades.

<Window x:Class = "WPFStyle.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace: WPFStyle" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <Button Content = "Button1" Height = "30" Width = "80" 
         Foreground = "Blue" FontSize = "12" Margin = "10"/> 
      <Button Content = "Button2" Height = "30" Width = "80" 
         Foreground = "Blue" FontSize = "12" Margin = "10"/> 
      <Button Content = "Button3" Height = "30" Width = "80" 
         Foreground = "Blue" FontSize = "12" Margin = "10"/> 
   </StackPanel> 
	
</Window>

Quando você olhar para o código acima, verá que para todos os botões a altura, largura, cor de primeiro plano, tamanho da fonte e propriedades de margem são iguais. Agora, quando o código acima for compilado e executado, a seguinte janela será exibida.

Agora vamos dar uma olhada no mesmo exemplo, mas desta vez, vamos usar style.

<Window x:Class = "XAMLStyle.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:local = "clr-namespace:XAMLStyle" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
	
   <Window.Resources> 
      <Style x:Key = "myButtonStyle" TargetType = "Button"> 
         <Setter Property = "Height" Value = "30" /> 
         <Setter Property = "Width" Value = "80" /> 
         <Setter Property = "Foreground" Value = "Blue" /> 
         <Setter Property = "FontSize" Value = "12" /> 
         <Setter Property = "Margin" Value = "10" /> 
      </Style> 
   </Window.Resources> 
	
   <StackPanel> 
      <Button Content = "Button1" Style = "{StaticResource myButtonStyle}" /> 
      <Button Content = "Button2" Style = "{StaticResource myButtonStyle}" /> 
      <Button Content = "Button3" Style="{StaticResource myButtonStyle}" /> 
   </StackPanel> 
	
</Window>

Os estilos são definidos no dicionário de recursos e cada estilo possui um identificador de chave exclusivo e um tipo de destino. Dentro de <style> você pode ver que várias tags setter são definidas para cada propriedade que será incluída no estilo.

No exemplo acima, todas as propriedades comuns de cada botão agora são definidas em estilo e, em seguida, o estilo é atribuído a cada botão com uma chave exclusiva, definindo a propriedade de estilo por meio da extensão de marcação StaticResource.

Quando você compila e executa o código acima, ele exibe a seguinte janela (a mesma saída).

A vantagem de fazer assim é imediatamente óbvia, podemos reutilizar esse estilo em qualquer lugar em seu escopo; e se precisarmos mudá-lo, simplesmente mudamos uma vez na definição de estilo em vez de em cada elemento.

Em que nível um estilo é definido limita instantaneamente o escopo desse estilo. Portanto, o escopo, ou seja, onde você pode usar o estilo, depende de onde você o definiu. Os estilos podem ser definidos nos seguintes níveis -

Sr. Não Níveis e descrição
1 Nível de controle

Definir um estilo no nível de controle só pode ser aplicado a esse controle específico. A seguir, é fornecido um exemplo de nível de controle em que o botão e o TextBlock têm seu próprio estilo.

2 Nível de Layout

Definir um estilo em qualquer nível de layout o tornará acessível apenas para aquele layout e seus elementos filho.

3 Nível da janela

Definir um estilo em um nível de janela pode torná-lo acessível a todos os elementos dessa janela.

4 Nível de Aplicação

Definir um estilo no nível do aplicativo pode torná-lo acessível em todo o aplicativo. Vamos pegar o mesmo exemplo, mas aqui colocaremos os estilos no arquivo app.xaml para torná-lo acessível em todo o aplicativo.

Um gatilho basicamente permite que você altere os valores da propriedade ou execute ações com base no valor de uma propriedade. Assim, ele permite que você altere dinamicamente a aparência e / ou comportamento de seu controle sem ter que criar um novo.

Os gatilhos são usados ​​para alterar o valor de qualquer propriedade, quando certas condições são satisfeitas. Os gatilhos geralmente são definidos em um estilo ou na raiz de um documento que são aplicados a esse controle específico. Existem três tipos de gatilhos -

  • Gatilhos de propriedade
  • Gatilhos de dados
  • Gatilhos de eventos

Gatilhos de propriedade

Em disparadores de propriedade, quando ocorre uma mudança em uma propriedade, ela trará uma mudança imediata ou animada em outra propriedade. Por exemplo, você pode usar um disparador de propriedade para alterar a aparência de um botão quando o mouse passa sobre o botão.

O código de exemplo a seguir mostra como alterar a cor de primeiro plano de um botão quando o mouse passa sobre o botão.

<Window x:Class = "WPFPropertyTriggers.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Window.Resources> 
      <Style x:Key = "TriggerStyle" TargetType = "Button"> 
         <Setter Property = "Foreground" Value = "Blue" /> 
         <Style.Triggers> 
            <Trigger Property = "IsMouseOver" Value = "True"> 
               <Setter Property = "Foreground" Value = "Green" /> 
            </Trigger> 
         </Style.Triggers> 
      </Style> 
   </Window.Resources> 
	
   <Grid> 
      <Button Width = "100" Height = "70"
         Style = "{StaticResource TriggerStyle}" Content = "Trigger"/> 
   </Grid> 
	
</Window>

Quando você compila e executa o código acima, ele irá produzir a seguinte janela -

Quando o mouse passa sobre o botão, sua cor de primeiro plano muda para verde.

Gatilhos de dados

Um acionador de dados executa algumas ações quando os dados vinculados satisfazem algumas condições. Vamos dar uma olhada no código XAML a seguir, no qual uma caixa de seleção e um bloco de texto são criados com algumas propriedades. Quando a caixa de seleção está marcada, ele mudará sua cor de primeiro plano para vermelho.

<Window x:Class = "WPFDataTrigger.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "Data Trigger" Height = "350" Width = "604">
	
   <StackPanel HorizontalAlignment = "Center"> 
      <CheckBox x:Name = "redColorCheckBox" 
         Content = "Set red as foreground color" Margin = "20"/> 
			
      <TextBlock Name = "txtblock" VerticalAlignment = "Center" 
         Text = "Event Trigger" FontSize = "24" Margin = "20"> 
         <TextBlock.Style> 
            <Style> 
               <Style.Triggers> 
                  <DataTrigger Binding = "{Binding ElementName = redColorCheckBox, Path = IsChecked}" 
                     Value = "true"> 
                     <Setter Property = "TextBlock.Foreground" Value = "Red"/> 
                     <Setter Property = "TextBlock.Cursor" Value = "Hand" /> 
                  </DataTrigger> 
               </Style.Triggers> 
            </Style> 
         </TextBlock.Style> 
      </TextBlock> 
		
   </StackPanel> 
	
</Window>

Quando o código acima for compilado e executado, ele produzirá a seguinte saída -

Ao marcar a caixa de seleção, o bloco de texto mudará sua cor de primeiro plano para vermelho.

Gatilhos de eventos

Um gatilho de evento executa algumas ações quando um evento específico é disparado. Normalmente é usado para realizar alguma animação no controle, como DoubleAnumatio, ColorAnimation, etc. No exemplo a seguir, criaremos um botão simples. Quando o evento de clique é disparado, ele expande a largura e a altura do botão.

<Window x:Class = "WPFEventTrigger.MainWindow"
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button Content = "Click Me" Width = "60" Height = "30">
		
         <Button.Triggers> 
            <EventTrigger RoutedEvent = "Button.Click"> 
               <EventTrigger.Actions> 
                  <BeginStoryboard> 
                     <Storyboard> 
							
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = 
                           "Width" Duration = "0:0:4"> 
                           <LinearDoubleKeyFrame Value = "60" KeyTime = "0:0:0"/> 
                           <LinearDoubleKeyFrame Value = "120" KeyTime = "0:0:1"/> 
                           <LinearDoubleKeyFrame Value = "200" KeyTime = "0:0:2"/> 
                           <LinearDoubleKeyFrame Value = "300" KeyTime = "0:0:3"/> 
                        </DoubleAnimationUsingKeyFrames>
								
                        <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = "Height" 
                           Duration = "0:0:4"> 
                           <LinearDoubleKeyFrame Value = "30" KeyTime = "0:0:0"/> 
                           <LinearDoubleKeyFrame Value = "40" KeyTime = "0:0:1"/> 
                           <LinearDoubleKeyFrame Value = "80" KeyTime = "0:0:2"/> 
                           <LinearDoubleKeyFrame Value = "150" KeyTime = "0:0:3"/> 
                        </DoubleAnimationUsingKeyFrames>
								
                     </Storyboard> 
                  </BeginStoryboard> 
               </EventTrigger.Actions> 
            </EventTrigger> 
         </Button.Triggers> 
			
      </Button> 
   </Grid> 
	
</Window>

Quando você compila e executa o código acima, ele irá produzir a seguinte janela -

Ao clicar no botão, você observará que ele começará a se expandir nas duas dimensões.

Recomendamos que você compile e execute os exemplos acima e aplique os gatilhos a outras propriedades também.

É um mecanismo sistemático de identificação e correção de bugs ou defeitos em um trecho de código que não se comportam da mesma forma que você espera. Depurar um aplicativo complexo em que os subsistemas estão fortemente acoplados não é fácil, porque corrigir bugs em um subsistema pode criar bugs em outro subsistema.

Depuração em C #

Em aplicativos WPF, os programadores lidam com duas linguagens, como C # e XAML. Se você estiver familiarizado com a depuração em qualquer linguagem procedural, como C # ou C / C ++ e também souber o uso de pontos de interrupção, poderá depurar a parte C # de seu aplicativo facilmente.

Vamos dar um exemplo simples para demonstrar como depurar um código C #. Crie um novo projeto WPF com o nomeWPFDebuggingDemo. Arraste quatro rótulos, três caixas de texto e um botão da caixa de ferramentas. Dê uma olhada no seguinte código XAML.

<Window x:Class = "WPFDebuggingDemo.Window1" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "Window1" Height = "400" Width = "604"> 
	
   <Grid> 
      <TextBox Height = "23" Margin = "0,44,169,0" Name = "textBox1"  
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" /> 
			
      <TextBox Height = "23" Margin = "0,99,169,0" Name = "textBox2"  
         VerticalAlignment = "Top" HorizontalAlignment = "Right" Width = "120" /> 
			
      <TextBox HorizontalAlignment = "Right" Margin = "0,153,169,0"  
         Name = "textBox3" Width = "120" Height = "23" VerticalAlignment = "Top" /> 
			
      <Label Height = "28" Margin = "117,42,0,0" Name = "label1"  
         VerticalAlignment = "Top" HorizontalAlignment = "Left" Width = "120">
         Item 1</Label> 
			
      <Label Height = "28" HorizontalAlignment = "Left"  
         Margin = "117,99,0,0" Name = "label2" VerticalAlignment = "Top" Width = "120">
         Item 2</Label> 
			
      <Label HorizontalAlignment = "Left" Margin = "117,153,0,181"  
         Name = "label3" Width = "120">Item 3</Label>
			
      <Button Height = "23" HorizontalAlignment = "Right" Margin = "0,0,214,127"
         Name = "button1" VerticalAlignment = "Bottom" Width = "75"  
         Click = "button1_Click">Total</Button> 
			
      <Label Height = "28" HorizontalAlignment = "Right"  
         Margin = "0,0,169,66" Name = "label4" VerticalAlignment = "Bottom" Width = "120"/> 
			
   </Grid> 
	
</Window>

A seguir está o código C # em que um evento de clique de botão é implementado.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text;
 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes;  

namespace WPFDebuggingDemo { 
   /// <summary> 
      /// Interaction logic for Window1.xaml 
   /// </summary> 
	
   public partial class Window1 : Window { 
	
      public Window1() {
         InitializeComponent();
      }
		
      private void button1_Click(object sender, RoutedEventArgs e) {
		
         if (textBox1.Text.Length > 0 && textBox2.Text.Length > 0 && textBox2.Text.Length > 0) {
            double total = Convert.ToDouble(textBox1.Text) + 
            Convert.ToDouble(textBox2.Text) + Convert.ToDouble(textBox3.Text); 
            label4.Content = total.ToString(); 
         } 
         else { 
            MessageBox.Show("Enter the value in all field.");
         } 
      } 
   } 
}

Quando você compila e executa o código acima, ele produzirá a seguinte janela. Agora insira os valores nas caixas de texto e pressione o botão Total. Você obterá o valor total após a soma de todos os valores inseridos nas caixas de texto.

Se você tentar inserir valores diferentes dos reais, o aplicativo acima travará. Para localizar e resolver o problema (por que ele está travando), você pode inserir pontos de interrupção no evento de clique do botão.

Vamos escrever "abc" no item 1 conforme mostrado abaixo.

Ao clicar no botão Total, você verá que o programa para no ponto de interrupção

Agora mova o cursor para a caixa de texto1.Texto e você verá que o programa está tentando adicionar abc valor com os outros valores, razão pela qual o programa está travando.

Depuração em XAML

Se você está esperando o mesmo tipo de depuração em XAML, ficará surpreso ao saber que ainda não é possível depurar o código XAML como depurar qualquer outro código de linguagem procedural. Quando você ouve o termo depuração no código XAML, significa tente encontrar um erro.

  • Na vinculação de dados, seus dados não aparecem na tela e você não sabe por quê

  • Ou um problema está relacionado a layouts complexos.

  • Ou um problema de alinhamento ou problemas na cor da margem, sobreposições, etc. com alguns modelos extensos como ListBox e caixa de combinação.

A depuração de um programa XAML é algo que você normalmente faz para verificar se suas ligações funcionam; e se não estiver funcionando, verifique o que está errado. Infelizmente, definir pontos de interrupção em associações XAML não é possível, exceto no Silverlight, mas podemos usar a janela Saída para verificar erros de associação de dados. Vamos dar uma olhada no código XAML a seguir para encontrar o erro na vinculação de dados.

<Window x:Class = "DataBindingOneWay.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <StackPanel Name = "Display"> 
         <StackPanel Orientation = "Horizontal" Margin = "50, 50, 0, 0"> 
            <TextBlock Text = "Name: " Margin = "10" Width = "100"/> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding FirstName}"/> 
         </StackPanel> 
			
         <StackPanel Orientation = "Horizontal" Margin = "50,0,50,0"> 
            <TextBlock Text = "Title: " Margin = "10" Width = "100"/> 
            <TextBlock Margin = "10" Width = "100" Text = "{Binding Title}" /> 
         </StackPanel> 
			
      </StackPanel> 
   </Grid> 
	
</Window>

As propriedades de texto de dois blocos de texto são definidas como “Nome” e “Título” estaticamente, enquanto outros dois blocos de texto As propriedades de texto são vinculadas a “Nome” e “Título”, mas as variáveis ​​de classe são Nome e Título na classe Funcionário que é mostrada abaixo.

Escrevemos intencionalmente um nome de variável incorreto para entender onde podemos encontrar esse tipo de erro quando a saída desejada não é exibida.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks;  

namespace DataBindingOneWay { 

   public class Employee { 
      public string Name { get; set; } 
      public string Title { get; set; }  
		
      public static Employee GetEmployee() { 
		
         var emp = new Employee() { 
            Name = "Ali Ahmed", Title = "Developer" 
         }; 
			
         return emp; 
      }  
   } 
}

Aqui está a implementação da classe MainWindow em código C #.

using System; 
using System.Windows; 
using System.Windows.Controls; 
 
namespace DataBindingOneWay { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         DataContext = Employee.GetEmployee(); 
      } 
   } 
}

Vamos executar este aplicativo e você pode ver imediatamente em nossa MainWindow que vinculamos com sucesso ao Title desse objeto Employee, mas o nome não está vinculado.

Para verificar o que aconteceu com o nome, vamos dar uma olhada na janela de saída, onde muitos logs são gerados.

O fácil de encontrar um erro é apenas pesquisar o erro e você encontrará o seguinte erro que diz “Erro de caminho BindingExpression: propriedade 'FirstName' não encontrada no 'objeto' '' Employe”

System.Windows.Data Error: 40 : BindingExpression path error: 'FirstName'
   property not found on 'object' ''Employee' (HashCode=11611730)'.
   BindingExpression:Path = FirstName; DataItem = 'Employee' (HashCode = 11611730);
   target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')

O que indica claramente que FirstName não é membro da classe Employee, portanto, ajuda a corrigir esse tipo de problema em seu aplicativo.

Ao alterar o FirstName para Name novamente, você verá a saída desejada.

Ferramentas de depuração de interface do usuário para XAML

Ferramentas de depuração de IU foram introduzidas para XAML com Visual Studio 2015 para inspecionar o código XAML em tempo de execução. Com a ajuda dessas ferramentas, o código XAML é apresentado na forma de uma árvore visual de seu aplicativo WPF em execução e também nas diferentes propriedades do elemento de interface do usuário na árvore. Para habilitar essas ferramentas, siga as etapas abaixo.

  • Vá para o menu Ferramentas e selecione Opções no menu Ferramentas.
  • Isso abrirá a seguinte caixa de diálogo.
  • Vá para Opções Gerais no item Depuração no lado esquerdo.
  • Marque a opção destacada, ou seja, “Habilitar ferramentas de depuração de interface do usuário para XAML” e clique no botão OK.

Agora execute qualquer aplicativo XAML ou use o seguinte código XAML.

<Window x:Class = "XAMLTestBinding.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <ComboBox Name = "comboBox"  Margin = "50" Width = "100"> 
         <ComboBoxItem Content = "Green" /> 
         <ComboBoxItem  Content = "Yellow" IsSelected = "True" />
         <ComboBoxItem Content = "Orange" /> 
      </ComboBox> 
		
      <TextBox  Name = "textBox" Margin = "50" Width = "100" Height = "23"
         VerticalAlignment = "Top" Text  =
         "{Binding ElementName = comboBox, Path = SelectedItem.Content, Mode = TwoWay, UpdateSourceTrigger = PropertyChanged}" 
         Background = "{Binding ElementName = comboBox, Path = SelectedItem.Content}"> 
      </TextBox> 
		
   </StackPanel> 
	
</Window>

Ao executar o aplicativo, ele mostrará a Árvore Visual Live onde todos os elementos são mostrados em uma árvore.

Esta Árvore Visual Live mostra a estrutura de layout completa para entender onde os elementos da IU estão localizados. Mas essa opção está disponível apenas no Visual Studio 2015. Se você estiver usando uma opção mais antiga do Visual Studio, não poderá usar essa ferramenta, no entanto, há outra ferramenta que pode ser integrada ao Visual Studio, como XAML Spy para Visual Studio . Você pode baixá-lo de xamlspy

Os aplicativos WPF permitem criar controles personalizados, o que torna muito fácil criar controles ricos em recursos e personalizáveis. Os controles personalizados são usados ​​quando todos os controles internos fornecidos pela Microsoft não atendem aos seus critérios ou você não deseja pagar por controles de terceiros.

Neste capítulo, você aprenderá como criar controles personalizados. Antes de começarmos a dar uma olhada nos controles personalizados, vamos primeiro dar uma olhada rápida em um controle do usuário.

Controle do usuário

Os controles do usuário fornecem uma maneira de coletar e combinar diferentes controles integrados e empacotá-los em XAML reutilizáveis. Os controles do usuário são usados ​​nos seguintes cenários -

  • Se o controle consiste em controles existentes, ou seja, você pode criar um único controle de vários controles já existentes.

  • Se o controle não precisar de suporte para temas. Os controles do usuário não oferecem suporte a personalizações complexas, modelos de controle e difíceis de definir.

  • Se um desenvolvedor preferir escrever controles usando o modelo code-behind onde uma visualização e, em seguida, um code behind direto para manipuladores de eventos.

  • Você não compartilhará seu controle entre os aplicativos.

Exemplo

Vamos para um exemplo de controle do usuário e siga as etapas fornecidas abaixo.

  • Crie um novo projeto WPF e, a seguir, clique com o botão direito na sua solução e selecione Adicionar> Novo Item ...

  • A seguinte janela será aberta. Agora selecioneUser Control (WPF) e chame-o de MyUserControl.

  • Clique no botão Adicionar e você verá que dois novos arquivos (MyUserControl.xaml e MyUserControl.cs) serão adicionados à sua solução.

Aqui está o código XAML no qual um botão e uma caixa de texto são criados com algumas propriedades no arquivo MyUserControl.xaml.

<UserControl x:Class = "WPFUserControl.MyUserControl" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006"  
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"  
   mc:Ignorable = "d" d:DesignHeight = "300" d:DesignWidth = "300"> 
	
   <Grid> 
      <TextBox Height = "23"  
         HorizontalAlignment = "Left"  
         Margin = "80,49,0,0" Name = "txtBox"  
         VerticalAlignment = "Top" Width = "200" /> 
			
      <Button Content = "Click Me"  
         Height = "23" HorizontalAlignment = "Left"  
         Margin = "96,88,0,0" Name = "button"  
         VerticalAlignment = "Top" Click = "button_Click" />    
   </Grid>
	
</UserControl>

A seguir está o código C # para o evento de clique de botão no arquivo MyUserControl.cs que atualiza a caixa de texto.

using System; 
using System.Windows; 
using System.Windows.Controls; 
 
namespace WPFUserControl {
   /// <summary>
      /// Interaction logic for MyUserControl.xaml 
   /// </summary> 
	
   public partial class MyUserControl : UserControl { 
	
      public MyUserControl() { 
         InitializeComponent(); 
      }  
		
      private void button_Click(object sender, RoutedEventArgs e) { 
         txtBox.Text = "You have just clicked the button"; 
      } 
   } 
}

Aqui está a implementação em MainWindow.xaml para adicionar o controle de usuário.

<Window x:Class = "XAMLUserControl.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:control = "clr-namespace:WPFUserControl" 
   Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid> 
      <control:MyUserControl/> 
   </Grid> 
	
</Window>

Quando você compila e executa o código acima, ele produzirá a seguinte janela.

Ao clicar no botão "Click Me", você notará que o texto dentro da caixa de texto é atualizado.

Controles personalizados

Um controle personalizado é uma classe que oferece seu próprio estilo e modelo, normalmente definidos em generic.xaml. Os controles personalizados são usados ​​nos seguintes cenários -

  • Se o controle não existe e você tem que criá-lo do zero.

  • Se você deseja estender ou adicionar funcionalidade a um controle preexistente, adicionando uma propriedade extra ou uma funcionalidade extra para se adequar ao seu cenário específico.

  • Se seus controles precisam oferecer suporte a temas e estilos.

  • Se você deseja compartilhar seu controle entre os aplicativos.

Exemplo

Vamos dar um exemplo para entender como funcionam os controles personalizados. Crie um novo projeto WPF e, a seguir, clique com o botão direito na sua solução e selecione Adicionar> Novo Item ...

Ele irá abrir a seguinte janela. Agora selecioneCustom Control (WPF) e nomeá-lo MyCustomControl.

Clique no botão Adicionar e você verá que dois novos arquivos (Themes / Generic.xaml e MyCustomControl.cs) serão adicionados à sua solução.

Aqui está o código XAML no qual o estilo é definido para o controle personalizado no arquivo Generic.xaml.

<ResourceDictionary 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFCustomControls">  
	
   <Style TargetType = "{x:Type local:MyCustomControl}"
      BasedOn = "{StaticResource {x:Type Button}}"> 
      <Setter Property = "Background" Value = "LightSalmon" /> 
      <Setter Property = "Foreground" Value = "Blue"/> 
   </Style> 
	
</ResourceDictionary>

Aqui está o código C # para a classe MyCustomControl que é herdado da classe do botão e no construtor ele substitui os metadados.

using System; 
using System.Windows; 
using System.Windows.Controls; 
 
namespace WPFCustomControls { 

   public class MyCustomControl : Button { 
	
      static MyCustomControl() { 
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), new
            FrameworkPropertyMetadata(typeof(MyCustomControl))); 
      } 
		
   } 
}

Aqui está a implementação de evento de clique de controle personalizado em C # que atualiza o texto do bloco de texto.

using System; 
using System.Windows; 
using System.Windows.Controls;

namespace WPFCustomControls { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void customControl_Click(object sender, RoutedEventArgs e) { 
         txtBlock.Text = "You have just click your custom control"; 
      }
		
   } 
}

Aqui está a implementação em MainWindow.xaml para adicionar o controle personalizado e um TextBlock.

<Window x:Class = "WPFCustomControls.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:control = "clr-namespace:WPFCustomControls" 
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <StackPanel> 
      <control:MyCustomControl x:Name = "customControl"  
         Content = "Click Me" Width = "70" 
         Margin = "10" Click = "customControl_Click"/> 
			
      <TextBlock Name = "txtBlock"  
         Width = "250" Height = "30"/> 
   </StackPanel>
	
</Window>

Quando você compila e executa o código acima, ele produzirá a seguinte janela com um controle personalizado que é um botão personalizado.

Ao clicar no botão personalizado, você verá que o texto dentro do bloco de texto é atualizado.

Uma exceção é qualquer condição de erro ou comportamento inesperado encontrado durante a execução de um programa. Exceções podem ser levantadas por vários motivos, alguns deles são os seguintes -

  • Falha em seu código ou no código que você chama (como uma biblioteca compartilhada),

  • Recursos indisponíveis do sistema operacional,

  • Condições inesperadas que um common language runtime encontra (como código que não pode ser verificado)

Sintaxe

As exceções têm a capacidade de transferir o fluxo de um programa de uma parte para outra. No .NET framework, o tratamento de exceções tem as seguintes quatro palavras-chave -

  • try - Neste bloco, o programa identifica uma determinada condição que levanta alguma exceção.

  • catch- A palavra-chave catch indica a captura de uma exceção. UMAtry bloco é seguido por um ou mais catch blocos para capturar uma exceção com um tratador de exceção no local de um programa onde você deseja tratar o problema.

  • finally- O bloco finally é usado para executar um determinado conjunto de instruções, seja uma exceção lançada ou não. Por exemplo, se você abrir um arquivo, ele deve ser fechado, independentemente de haver ou não uma exceção.

  • throw- Um programa lança uma exceção quando um problema aparece. Isso é feito usando uma palavra-chave throw.

A sintaxe para usar essas quatro palavras-chave é a seguinte -

try { 
   ///This will still trigger the exception 
} 
catch (ExceptionClassName e) { 
   // error handling code 
} 
catch (ExceptionClassName e) { 
   // error handling code
}
catch (ExceptionClassName e) { 
   // error handling code 
} 
finally { 
   // statements to be executed 
}

Várias instruções catch são usadas nos casos em que um bloco try pode gerar mais de uma exceção, dependendo da situação de um fluxo de programa.

Hierarquia

Quase todas as classes de exceção na estrutura .NET são derivadas direta ou indiretamente da classe Exception. As classes de exceção mais importantes derivadas da classe Exception são -

  • ApplicationException class- Suporta exceções geradas por programas. Quando o desenvolvedor deseja definir a exceção, a classe deve ser derivada desta classe.

  • SystemException class- É a classe base para todas as exceções de sistema de tempo de execução predefinidas. A hierarquia a seguir mostra as exceções padrão fornecidas pelo tempo de execução.

A tabela a seguir lista as exceções padrão fornecidas pelo tempo de execução e as condições sob as quais você deve criar uma classe derivada.

Tipo de exceção Tipo de base Descrição
Exception Objeto Classe base para todas as exceções.
SystemException Exceção Classe base para todos os erros gerados pelo tempo de execução.
IndexOutOfRangeException SystemException Lançado pelo tempo de execução apenas quando uma matriz é indexada incorretamente.
NullReferenceException SystemException Lançado pelo tempo de execução apenas quando um objeto nulo é referenciado.
AccessViolationException SystemException Lançado pelo tempo de execução apenas quando a memória inválida é acessada.
InvalidOperationException SystemException Lançado por métodos quando em um estado inválido.
ArgumentException SystemException Classe base para todas as exceções de argumento.
ArgumentNullException ArgumentException Lançado por métodos que não permitem que um argumento seja nulo.
ArgumentOutOfRangeException ArgumentException Lançado por métodos que verificam se os argumentos estão em um determinado intervalo.
ExternalException SystemException Classe base para exceções que ocorrem ou são destinadas a ambientes fora do tempo de execução.
SEHException Exceção externa Exceção que encapsula informações de manipulação de exceção estruturada do Win32.

Exemplo

Vamos dar um exemplo simples para entender melhor o conceito. Comece criando um novo projeto WPF com o nomeWPFExceptionHandling.

Arraste uma caixa de texto da caixa de ferramentas para a janela de design. O código XAML a seguir cria uma caixa de texto e a inicializa com algumas propriedades.

<Window x:Class = "WPFExceptionHandling.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFExceptionHandling"
   mc:Ignorable = "d" 
   Title = "MainWindow" Height = "350" Width = "604">
	
   <Grid> 
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"
         Height = "241" Margin = "70,39,0,0" TextWrapping = "Wrap" 
         VerticalAlignment = "Top" Width = "453"/> 
   </Grid> 
	
</Window>

Aqui está a leitura do arquivo com tratamento de exceção em C #.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling { 

   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      }
		
      void ReadFile(int index) { 
         string path = @"D:\Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) {
            MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message);
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

Quando você compila e executa o código acima, ele irá produzir a seguinte janela na qual um texto é exibido dentro da caixa de texto.

Quando há uma exceção levantada ou você a lança manualmente (como no código a seguir), ele mostrará uma caixa de mensagem com erro.

using System; 
using System.IO; 
using System.Windows;

namespace WPFExceptionHandling {
 
   public partial class MainWindow : Window {
	
      public MainWindow() { 
         InitializeComponent(); 
         ReadFile(0); 
      } 
		
      void ReadFile(int index) { 
         string path = @"D:\Test.txt"; 
         StreamReader file = new StreamReader(path); 
         char[] buffer = new char[80]; 
			
         try { 
            file.ReadBlock(buffer, index, buffer.Length); 
            string str = new string(buffer); 
            throw new Exception(); 
            str.Trim(); 
            textBox.Text = str; 
         }
         catch (Exception e) { 
            MessageBox.Show("Error reading from "+ path + "\nMessage = "+ e.Message); 
         } 
         finally { 
            if (file != null) { 
               file.Close(); 
            } 
         } 
      } 
   } 
}

Quando uma exceção é levantada durante a execução do código acima, ele exibirá a seguinte mensagem.

Recomendamos que você execute o código acima e experimente seus recursos.

Localização é a tradução dos recursos do aplicativo em versões localizadas para as culturas específicas que o aplicativo suporta.

Quando você desenvolve seu aplicativo e ele está disponível em apenas um idioma, você está limitando o número de clientes e o tamanho do seu negócio. Se você deseja aumentar sua base de clientes, o que também aumentará seus negócios, seu produto deve estar disponível e acessível para um público global. Custo-beneficiolocalization do seu produto é uma das maneiras melhores e mais econômicas de alcançar mais clientes.

No WPF, os aplicativos localizáveis ​​são muito fáceis de criar com resxarquivo que é a solução mais simples para localização. Vamos dar um exemplo simples para entender como funciona -

  • Crie um novo projeto WPF com o nome WPFLocalization.

  • Em seu explorador de soluções, você verá o arquivo Resources.resx na pasta Propriedades.

  • Altere o modificador de acesso de interno para público para que possa ser acessado no arquivo XAML.

  • Agora adicione o nome e os valores da seguinte string que usaremos em nosso aplicativo.

  • Faça duas cópias do arquivo Resources.resx com os nomes Resources.en.resx e Resources.ru-RU.resx. Essas são convenções de nomenclatura específicas para o idioma e o nome do país / região e podem ser encontradas em National Language Support (NLS) API Reference (https://msdn.microsoft.com/en-us/goglobal/bb896001.aspx ) página.

  • Altere os valores em Resources.ru-RU.resx para palavras russas, conforme mostrado abaixo.

  • Vamos para a janela de design e arrastar três caixas de texto, três rótulos e três botões.

  • No arquivo XAML, primeiro adicione a declaração de namespace para usar os recursos de localização xmlns: p = "clr-namespace: WPFLocalization.Properties"

  • Defina as propriedades de todos os controles conforme mostrado abaixo. Neste exemplo, não usaremos strings codificadas para o conteúdo de rótulos, botões e Título da janela no arquivo XAML. Estaremos usando as strings que são definidas em arquivos * .resx. Por exemplo, para o Título da janela, usamos a string Título que é definida no arquivo * .resx como este “Título =" {x: Estático p: Recursos.Título} "”

  • Aqui está o arquivo XAML no qual os controles são criados e inicializados com propriedades diferentes.

<Window x:Class = "WPFLocalization.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFLocalization" 
   xmlns:p = "clr-namespace:WPFLocalization.Properties"
   Title = "{x:Static p:Resources.Title}" Height = "350" Width = "604">
	
   <Grid> 
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left" Height = "23" 
         Margin = "128,45,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/>
			
      <Label x:Name = "label" Content = "{x:Static p:Resources.Name}"
          HorizontalAlignment = "Left" Margin = "52,45,0,0" VerticalAlignment = "Top" Width = "86"/>
			 
      <TextBox x:Name = "textBox1" HorizontalAlignment = "Left" Height = "23" 
         Margin = "128,102,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "304"/> 
			
      <Label x:Name = "label1" Content = "{x:Static p:Resources.Address}" 
         HorizontalAlignment = "Left" Margin = "52,102,0,0" VerticalAlignment = "Top" Width = "86"/>
			
      <TextBox x:Name = "textBox2" HorizontalAlignment = "Left" Height = "23" 
         Margin = "128,157,0,0" TextWrapping = "Wrap" VerticalAlignment = "Top" Width = "80"/>
			
      <Label x:Name = "label2" Content = "{x:Static p:Resources.Age}" 
         HorizontalAlignment = "Left" Margin = "52,157,0,0" VerticalAlignment = "Top" Width = "86"/>
			
      <Button x:Name = "button" Content = "{x:Static p:Resources.OK_Button}" 
         HorizontalAlignment = "Left" Margin = "163,241,0,0" VerticalAlignment = "Top" Width = "75"/> 
			
      <Button x:Name = "button1" Content = "{x:Static p:Resources.Cancel_Button}" 
         HorizontalAlignment = "Left" Margin = "282,241,0,0" VerticalAlignment = "Top" Width = "75"/>
			
      <Button x:Name = "button2" Content = "{x:Static p:Resources.Help_Button}" 
         HorizontalAlignment = "Left" Margin = "392,241,0,0" VerticalAlignment = "Top" Width = "75"/> 
   </Grid> 
	
 </Window>
  • Quando o código acima for compilado e executado, você verá a seguinte janela que contém diferentes controles.

  • Por padrão, o programa usa o padrão Resources.resx. Se quiser mostrar o texto no idioma russo definido no arquivo Resources.ru-RU.resx, você precisará definir a cultura explicitamente quando o programa iniciar no arquivo App.xaml, conforme mostrado abaixo.

using System.Windows;

namespace WPFLocalization {
   /// <summary> 
      /// Interaction logic for App.xaml 
   /// </summary> 
	
   public partial class App : Application {
	
      App() { 
         System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("ru-RU");
         //System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en"); 
      } 
   } 
}

Ao executar seu aplicativo, você verá todo o texto no idioma russo.

Recomendamos que você execute o código acima e crie arquivos resx para outras culturas também.

No WPF, uma interação mostra como uma visualização interage com os controles localizados nessa visualização. As interações mais comumente conhecidas são de dois tipos -

  • Behaviors
  • Arrastar e soltar

Comportamentos

Os comportamentos foram introduzidos com o Expression Blend 3, que pode encapsular algumas das funcionalidades em um componente reutilizável. Para adicionar comportamentos adicionais, você pode anexar esses componentes aos controles. Os comportamentos fornecem mais flexibilidade para projetar facilmente interações complexas do usuário.

Vamos dar uma olhada em um exemplo simples no qual um comportamento ControlStoryBoardAction é anexado aos controles.

  • Crie um novo projeto WPF com o nome WPFBehavior.

  • O código XAML a seguir cria uma elipse e dois botões para controlar o movimento da elipse.

<Window 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFBehaviors" 
   xmlns:i = "http://schemas.microsoft.com/expression/2010/interactivity" 
   xmlns:ei = "http://schemas.microsoft.com/expression/2010/interactions" 
   x:Class = "WPFBehaviors.MainWindow" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604">
	
   <Window.Resources> 
      <Storyboard x:Key = "Storyboard1" RepeatBehavior = "Forever" AutoReverse = "True"> 
		
         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty =
            "(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.X)"
            Storyboard.TargetName = "ellipse"> 
            <EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "301.524"/> 
            <EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "2.909"/> 
         </DoubleAnimationUsingKeyFrames>
			
         <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty = 
            "(UIElement.RenderTransform).(TransformGroup.Children )[3].(TranslateTransform.Y)"
            Storyboard.TargetName = "ellipse"> 
            <EasingDoubleKeyFrame KeyTime = "0:0:1" Value = "-0.485"/> 
            <EasingDoubleKeyFrame KeyTime = "0:0:2" Value = "0"/> 
         </DoubleAnimationUsingKeyFrames> 
			
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
            Storyboard.TargetName = "button"> 
            <DiscreteObjectKeyFrame KeyTime = "0" Value = "Play"/> 
         </ObjectAnimationUsingKeyFrames>
			
         <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty = "(ContentControl.Content)"
            Storyboard.TargetName = "button1"> 
            <DiscreteObjectKeyFrame KeyTime = "0" Value = "Stop"/> 
            <DiscreteObjectKeyFrame KeyTime = "0:0:2" Value = "Stop"/> 
         </ObjectAnimationUsingKeyFrames> 
      </Storyboard> 
   </Window.Resources> 
	
   <Window.Triggers> 
      <EventTrigger RoutedEvent = "FrameworkElement.Loaded"> 
         <BeginStoryboard Storyboard = "{StaticResource Storyboard1}"/> 
      </EventTrigger> 
   </Window.Triggers> 
	
   <Grid> 
      <Ellipse x:Name = "ellipse" Fill = "#FFAAAAC5" HorizontalAlignment = "Left"
         Height = "50.901" Margin = "49.324,70.922,0,0" Stroke = "Black"
         VerticalAlignment = "Top" Width = "73.684" RenderTransformOrigin = "0.5,0.5"> 
         <Ellipse.RenderTransform> 
            <TransformGroup> 
               <ScaleTransform/> 
               <SkewTransform/> 
               <RotateTransform/> 
               <TranslateTransform/> 
            </TransformGroup> 
         </Ellipse.RenderTransform> 
      </Ellipse>
		
      <Button x:Name = "button" Content = "Play" HorizontalAlignment = "Left" Height = "24.238"
         Margin = "63.867,0,0,92.953" VerticalAlignment = "Bottom" Width = "74.654"> 
         <i:Interaction.Triggers> 
            <i:EventTrigger EventName = "Click"> 
               <ei:ControlStoryboardAction Storyboard = "{StaticResource Storyboard1}"/> 
            </i:EventTrigger> 
         </i:Interaction.Triggers> 
      </Button>
		
      <Button x:Name = "button1" Content = "Stop" HorizontalAlignment = "Left" Height = "24.239"
         Margin = "160.82,0,0,93.922" VerticalAlignment = "Bottom" Width = "75.138"> 
         <i:Interaction.Triggers> 
            <i:EventTrigger EventName = "Click"> 
               <ei:ControlStoryboardAction ControlStoryboardOption = "Stop"
                  Storyboard = "{StaticResource Storyboard1}"/> 
            </i:EventTrigger> 
         </i:Interaction.Triggers> 
      </Button> 
		
   </Grid> 
</Window>

Quando você compila e executa o código acima, ele produzirá a seguinte janela que contém uma elipse e dois botões.

Quando você pressiona o botão play, ele começa a se mover da esquerda para a direita e depois retorna à sua posição original. O botão de parada irá parar o movimento da elipse.

Arrastar e soltar

Arrastar e soltar na interface do usuário pode aumentar significativamente a eficiência e a produtividade do aplicativo. Existem muito poucos aplicativos nos quais os recursos de arrastar e soltar são usados ​​porque as pessoas acham que é difícil de implementar. Até certo ponto, é difícil lidar com um recurso de arrastar e soltar, mas no WPF, você pode lidar com isso facilmente.

Vamos dar um exemplo simples para entender como funciona. Criaremos um aplicativo no qual você pode arrastar e soltar cores de um retângulo para outro.

  • Crie um novo projeto WPF com o nome WPFDragAndDrop.

  • Arraste cinco retângulos para a janela de design e defina as propriedades conforme mostrado no seguinte arquivo XAML.

<Window x:Class = "WPFDragAndDrop.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFDragAndDrop" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "402.551" Width = "604"> 
	
   <Grid> 
      <Rectangle Name = "Target" Fill = "AliceBlue" HorizontalAlignment = "Left"  
         Height = "345" Margin = "10,10,0,0" Stroke = "Black"  
         VerticalAlignment = "Top" Width = "387" AllowDrop = "True" Drop = "Target_Drop"/> 
			
      <Rectangle Fill = "Beige" HorizontalAlignment = "Left" Height = "65"  
         Margin = "402,10,0,0" Stroke = "Black" VerticalAlignment = "Top"  
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/> 
			
      <Rectangle Fill = "LightBlue" HorizontalAlignment = "Left" Height = "65"  
         Margin = "402,80,0,0" Stroke = "Black" VerticalAlignment = "Top"  
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/> 
			
      <Rectangle Fill = "LightCoral" HorizontalAlignment = "Left" Height = "65"  
         Margin = "402,150,0,0" Stroke = "Black" VerticalAlignment = "Top"  
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/> 
			
      <Rectangle Fill = "LightGray" HorizontalAlignment = "Left" Height = "65"  
         Margin = "402,220,0,0" Stroke = "Black" VerticalAlignment = "Top"  
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/> 
			
      <Rectangle Fill = "OliveDrab" HorizontalAlignment = "Left" Height = "65"  
         Margin = "402,290,0,-7" Stroke = "Black" VerticalAlignment = "Top"  
         Width = "184" MouseLeftButtonDown = "Rect_MLButtonDown"/>  
   </Grid> 
	
</Window>
  • O primeiro retângulo é o retângulo de destino, então o usuário pode arrastar a cor do outro retângulo para o retângulo de destino.

  • A seguir estão as implementações de eventos em C # para arrastar e soltar.

using System.Windows; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Shapes; 
 
namespace WPFDragAndDrop { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void Rect_MLButtonDown(object sender, MouseButtonEventArgs e) { 
         Rectangle rc = sender as Rectangle; 
         DataObject data = new DataObject(rc.Fill); 
         DragDrop.DoDragDrop(rc, data,DragDropEffects.Move); 
      }  
		
      private void Target_Drop(object sender, DragEventArgs e) { 
         SolidColorBrush scb = (SolidColorBrush)e.Data.GetData(typeof(SolidColorBrush)); 
         Target.Fill = scb; 
      } 
   } 
}

Quando você executa seu aplicativo, ele produzirá a seguinte janela.

Se você arrastar uma cor do retângulo à direita e soltá-la no retângulo grande à esquerda, verá seu efeito imediatamente.

Vamos arrastar o do lado direito.

Você pode ver que a cor do retângulo de destino mudou. Recomendamos que você execute o código acima e experimente seus recursos.

O WPF oferece uma ampla variedade de gráficos 2D que podem ser aprimorados de acordo com os requisitos de sua aplicação. WPF oferece suporte a objetos de desenho e forma que são usados ​​para desenhar conteúdo gráfico.

Formas e Desenho

  • A classe Shape é derivada da classe FrameworkElement. Objetos Shape podem ser usados ​​dentro de painéis e na maioria dos controles.

  • O WPF fornece alguns objetos de forma básicos que são derivados da classe Forma, como Elipse, Linha, Caminho, Polígono, Polilinha e Retângulo.

  • Os objetos de desenho, por outro lado, não derivam da classe FrameworkElement e fornecem uma implementação mais leve.

  • Os objetos de desenho são mais simples em comparação com os objetos de forma. Eles também têm melhores características de desempenho.

Exemplo

Vamos dar um exemplo simples para entender como usar objetos de diferentes formas.

  • Crie um novo projeto WPF com o nome WPF2DGraphics.

  • O código a seguir cria diferentes tipos de formas.

<Window x:Class = "WPF2DGraphics.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPF2DGraphics" 
   xmlns:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"  
   mc:Ignorable = "PresentationOptions" Title = "MainWindow" Height = "400" Width = "604"> 
	
   <StackPanel> 
      <Ellipse Width = "100" Height = "60" Name = "sample" Margin = "10"> 
         <Ellipse.Fill> 
            <RadialGradientBrush> 
               <GradientStop Offset = "0" Color = "AliceBlue"/> 
               <GradientStop Offset = "1" Color = "Gray"/> 
               <GradientStop Offset = "2" Color = "Red"/> 
            </RadialGradientBrush> 
         </Ellipse.Fill> 
      </Ellipse>
		
      <Path Stroke = "Red" StrokeThickness = "5" Data = "M 10,70 L 200,70"
         Height = "42.085" Stretch = "Fill" Margin = "140.598,0,146.581,0" /> 
      <Path Stroke = "BlueViolet" StrokeThickness = "5" Data = "M 20,100 A 100,56 42 1 0 200,10"
         Height = "81.316" Stretch = "Fill" Margin = "236.325,0,211.396,0" /> 
			
      <Path Fill = "LightCoral" Margin = "201.424,0,236.325,0"
         Stretch = "Fill" Height = "124.929"> 
         <Path.Data> 
            <PathGeometry> 
               <PathFigure StartPoint = "50,0" IsClosed = "True"> 
                  <LineSegment Point = "100,50"/> 
                  <LineSegment Point = "50,100"/> 
                  <LineSegment Point = "0,50"/> 
               </PathFigure> 
            </PathGeometry> 
         </Path.Data> 
      </Path> 
		
   </StackPanel> 
	
</Window>

Quando você compila e executa o código acima, ele produzirá uma elipse, uma linha reta, um arco e um polígono.

Exemplo

Vamos dar uma olhada em outro exemplo que mostra como pintar uma área com um desenho.

  • Crie um novo projeto WPF com o nome WPF2DGraphics1.

  • O código XAML a seguir mostra como pintar de forma diferente com desenho de imagem.

<Window x:Class = "WPF2DGraphics1.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:PresentationOptions = "http://schemas.microsoft.com/winfx/2006/xaml/present ation/options"  
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   mc:Ignorable = "PresentationOptions" 
   xmlns:local = "clr-namespace:WPF2DGraphics1" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Border BorderBrush = "Gray" BorderThickness = "1"  
         HorizontalAlignment = "Left" VerticalAlignment = "Top" 
         Margin = "20"> 
			
         <Image Stretch = "None">
            <Image.Source> 
               <DrawingImage PresentationOptions:Freeze = "True"> 
					
                  <DrawingImage.Drawing> 
                     <DrawingGroup> 
                        <ImageDrawing Rect = "300,100,300,180" ImageSource = "Images\DSC_0104.JPG"/> 
                        <ImageDrawing Rect = "0,100,250,100" ImageSource = "Images\DSC_0104.JPG"/> 
                        <ImageDrawing Rect = "150,0,25,25" ImageSource = "Images\DSC_0104.JPG"/> 
                        <ImageDrawing Rect = "0,0,75,75" ImageSource = "Images\DSC_0104.JPG"/> 
                     </DrawingGroup> 
                  </DrawingImage.Drawing> 
						
               </DrawingImage> 
            </Image.Source> 
         </Image> 
			
      </Border> 
   </Grid> 
	
</Window>

Quando você executa seu aplicativo, ele produzirá a seguinte saída -

Recomendamos que você execute o código acima e tente mais formas e desenhos 2D.

O Windows Presentation Foundation (WPF) fornece uma funcionalidade para desenhar, transformar e animar gráficos 3D de acordo com os requisitos do aplicativo. Ele não oferece suporte para o desenvolvimento de jogos 3D completos, mas em algum nível, você pode criar gráficos 3D.

Ao combinar gráficos 2D e 3D, você também pode criar controles ricos, fornecer ilustrações complexas de dados ou aprimorar a experiência do usuário na interface de um aplicativo. O elemento Viewport3D hospeda um modelo 3D em nosso aplicativo WPF.

Exemplo

Vamos dar um exemplo simples para entender como usar gráficos 3D.

  • Crie um novo projeto WPF com o nome WPF3DGraphics.

  • O código XAML a seguir mostra como criar um objeto 2D usando geometria 3D.

<Window x:Class = "WPF3DGraphics.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPF3DGraphics" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "500" Width = "604"> 
	
   <Grid> 
      <Viewport3D> 
		
         <Viewport3D.Camera> 
            <PerspectiveCamera Position = "2,0,10" LookDirection = "0.2,0.4,-1"
               FieldOfView = "65" UpDirection = "0,1,0" /> 
         </Viewport3D.Camera> 
			
         <ModelVisual3D> 
            <ModelVisual3D.Content> 
               <Model3DGroup> 
                  <AmbientLight Color = "Bisque" /> 
						
                  <GeometryModel3D> 
                     <GeometryModel3D.Geometry> 
                        <MeshGeometry3D Positions = "0,0,0 0,8,0 10,0,0 8,8,0"
                           Normals = "0,0,1 0,0,1 0,0,1 0,0,1" TriangleIndices = "0,2,1 1,2,3"/> 
                     </GeometryModel3D.Geometry>
							
                     <GeometryModel3D.Material> 
                        <DiffuseMaterial Brush = "Bisque" /> 
                     </GeometryModel3D.Material> 
                  </GeometryModel3D>
						
               </Model3DGroup> 
            </ModelVisual3D.Content> 
         </ModelVisual3D> 
			
      </Viewport3D> 
   </Grid> 
	
</Window>

Quando você compila e executa o código acima, ele irá produzir um objeto 2D em 3D.

Exemplo

Vamos dar uma olhada em outro exemplo que mostra um objeto 3D.

  • Crie um novo projeto WPF com o nome WPF3DGraphics1

  • O código XAML a seguir cria um objeto 3D e um controle deslizante. Com a ajuda do controle deslizante, você pode girar este objeto 3D.

<Window x:Class = "WPF3DGraphics1.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPF3DGraphics1" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "525"> 
	
   <Grid>
      <Viewport3D Name="viewport3D1">
		
         <Viewport3D.Camera> 
            <PerspectiveCamera x:Name = "camMain" Position = "6 5 4" LookDirection = "-6 -5 -4"> 
            </PerspectiveCamera> 
         </Viewport3D.Camera>
		
         <ModelVisual3D> 
            <ModelVisual3D.Content> 
               <DirectionalLight x:Name = "dirLightMain" Direction = "-1,-1,-1"> 
               </DirectionalLight> 
            </ModelVisual3D.Content> 
         </ModelVisual3D>
		
         <ModelVisual3D x:Name = "MyModel"> 
            <ModelVisual3D.Content> 
               <GeometryModel3D>
				
                  <GeometryModel3D.Geometry>
                     <MeshGeometry3D x:Name = "meshMain"
                        Positions = "0 0 0  1 0 0  0 1 0  1 1 0  0 0 1  1 0 1  0 1 1  0 1 1"  
                        TriangleIndices = "2 3 1  3 1 0  7 1 3  7 5 1  6 5 7  6 4 5  6 2 0
                        2 0 4  2 7 3  2 6 7  0 1 5  0 5 4"> 
                     </MeshGeometry3D> 
                  </GeometryModel3D.Geometry> 
					
                  <GeometryModel3D.Material> 
                     <DiffuseMaterial x:Name = "matDiffuseMain">
                        <DiffuseMaterial.Brush> 
                           <SolidColorBrush Color = "Bisque"/> 
                        </DiffuseMaterial.Brush> 
                     </DiffuseMaterial> 
                  </GeometryModel3D.Material> 
					
               </GeometryModel3D>
            </ModelVisual3D.Content>
			 
            <ModelVisual3D.Transform>                         
               <RotateTransform3D> 
                  <RotateTransform3D.Rotation> 
                     <AxisAngleRotation3D x:Name = "rotate" Axis = "1 2 1"/> 
                  </RotateTransform3D.Rotation> 
               </RotateTransform3D>
            </ModelVisual3D.Transform> 
			 
         </ModelVisual3D> 
      </Viewport3D>
		
      <Slider Height = "23" HorizontalAlignment = "Left"  
         Margin = "145,271,0,0" Name = "slider1" 
         VerticalAlignment = "Top" Width = "269"  
         Maximum = "360" 
         Value = "{Binding ElementName = rotate, Path=Angle}" /> 
			
   </Grid> 
	
</Window>

Quando você executa seu aplicativo, ele produz um objeto 3D e um controle deslizante em sua janela.

Quando você desliza o controle deslizante, o objeto na janela também gira.

Recomendamos que você execute o código acima e tente mais geometria 3D.

Os aplicativos WPF suportam vídeo e áudio usando MediaElement. Ele permite que você integre áudio e vídeo em um aplicativo. A classe MediaElement funciona de maneira semelhante à classe Image. Você apenas aponta para a mídia e ela o processa. A principal diferença é que será uma imagem em movimento, mas se você apontar para o arquivo que contém apenas áudio e nenhum vídeo, como um MP3, ela irá reproduzi-la sem mostrar nada na tela.

WPF oferece suporte a todos os tipos de formato de vídeo / áudio, dependendo da configuração da máquina. Se um arquivo de mídia reproduz um Media Player, ele também funcionará em WPF na mesma máquina.

Exemplo

Vamos dar um exemplo para entender como integrar multimídia em seu aplicativo.

  • Crie um novo projeto WPF com o nome WPFMultimedia.

  • O código XAML a seguir cria um elemento de mídia e três botões e os inicializa com algumas propriedades.

<Window x:Class = "WPFMultimedia.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFMultimedia" 
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <StackPanel HorizontalAlignment = "Center" VerticalAlignment = "Center"> 
         <MediaElement Name = "myMedia" Source = "D:\MicrosoftMVA.mp4" 
            LoadedBehavior = "Manual" Width = "591" Height = "274" /> 
         <StackPanel Orientation = "Horizontal" Margin = "0,10,0,0">
            <Button Content = "Play" Margin = "0,0,10,0" Padding = "5" Click = "mediaPlay" /> 
            <Button Content = "Pause" Margin = "0,0,10,0" Padding = "5" Click = "mediaPause" />
            <Button x:Name = "muteButt" Content = "Mute" Padding = "5" Click = "mediaMute" /> 
         </StackPanel> 
      </StackPanel>
   </Grid> 
	
</Window>

Aqui está a implementação de eventos Click em C # para botões diferentes.

using System; 
using System.Windows; 
 
namespace WPFMultimedia { 

   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
         myMedia.Volume = 100; 
         myMedia.Play(); 
      } 
		
      void mediaPlay(Object sender, EventArgs e) { 
         myMedia.Play(); 
      }  
		
      void mediaPause(Object sender, EventArgs e) { 
         myMedia.Pause();
      } 
		
      void mediaMute(Object sender, EventArgs e) { 
		
         if (myMedia.Volume == 100) { 
            myMedia.Volume = 0; 
            muteButt.Content = "Listen"; 
         } 
         else { 
            myMedia.Volume = 100; 
            muteButt.Content = "Mute"; 
         } 
      } 
   } 
}

Quando você compila e executa o código acima, ele produzirá a seguinte janela. Você pode reproduzir o vídeo e controlar sua reprodução com os três botões.

Com os botões, você pode pausar, silenciar e reproduzir o vídeo.

Sintetizador de Fala

WPF possui recursos para converter texto em fala. Esta API está incluída no namespace System.Speech.SpeechSynthesizer classe transforma texto em palavras faladas.

Exemplo

Vamos dar uma olhada em um exemplo simples.

  • Crie um novo projeto WPF com o nome WPFTextToSpeech.

  • Precisaremos do assembly System.Speech para adicionar como referência para SpeechSynthesizer classe para trabalhar.

  • Clique com o botão direito em References e selecione Add Reference.

  • A caixa de diálogo Gerenciador de referências será aberta. Agora marque a caixa de seleção System.Speech

  • Clique no botão Ok. Você pode ver a montagem System.Speech em suas referências.

  • Agora arraste um botão e uma caixa de texto para a janela de design da caixa de ferramentas.

  • O código XAML a seguir cria um botão e uma caixa de texto e os inicializa com algumas propriedades.

<Window x:Class = "WPFTextToSpeech.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:d = "http://schemas.microsoft.com/expression/blend/2008" 
   xmlns:mc = "http://schemas.openxmlformats.org/markup-compatibility/2006" 
   xmlns:local = "clr-namespace:WPFTextToSpeech"
   mc:Ignorable = "d" Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <Button x:Name = "button" Content = "Speak"  
         HorizontalAlignment = "Left" Margin = "218,176,0,0"  
         VerticalAlignment = "Top" Width = "75"/> 
			
      <TextBox x:Name = "textBox" HorizontalAlignment = "Left"  
         Height = "23" Margin = "60,104,0,0" TextWrapping = "Wrap"  
         VerticalAlignment = "Top" Width = "418"/> 
   </Grid> 
	
</Window>
  • Aqui está a implementação simples em C # que converterá o texto dentro da caixa de texto em palavras faladas.

using System.Speech.Synthesis; 
using System.Windows; 
 
namespace WPFTextToSpeech { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      } 
		
      private void button_Click(object sender, RoutedEventArgs e) { 
		
         if (textBox.Text != "") {
            SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer(); 
            speechSynthesizer.Speak(textBox.Text);  
         } 
         else { 
            MessageBox.Show("Write some thing in the textbox!");
         } 
      } 
   }
}

Quando você compila e executa o código acima, ele produzirá a seguinte janela. Agora, digite Hello World dentro da caixa de texto e clique no botão Speak.

Ele produzirá o som "Hello World". Se você não digitar nada na caixa de texto, a seguinte mensagem aparecerá.

Recomendamos que você execute os exemplos acima.