Primeiras aulas do curso C#: Eventos, Delegates e Lambda

C#: Eventos, Delegates e Lambda

Comportamentos e Eventos - Introdução

Olá! Sou o instrutor Guilherme Matheus, e bem-vindas e bem-vindos ao curso de Eventos,Delegatens e Lambda da Alura. Começaremos discutindo sobre eventos, e como esse recurso da linguagem nos ajuda a adicionar, por exemplo, comportamentos em itens de interface gráfica, como um botão e lista. Eventos não são apenas importantes nesse tipo de projeto, mas também em serviços do Windows, pois tratamos eventos quando o serviço começa a funcionar e recebe uma pausa.

Aprenderemos também sobre delegates, e usar recursos da linguagem para termos um método fortemente tipado, desse modo usar um método e uma função como objetos. Veremos, ainda, que expressões lambda podem nos ajudar muito nas tarefas do projeto. Passaremos por diversas implementações dentro do .NET: como EventArgs, EvendHandler e até casos mais complexos como Func<T e TResult, delegates de função genéricos. Passaremos, ainda, pela classe Delegante e aprenderemos quais operações podemos realizar para atuar nos métodos, além de diversas outras implementações ao longo do curso.

Discutiremos sobre a Evolução da Sintaxe do C#, e como métodos anônimos vão nos ajudar a criar métodos e delegates em lugares pontuais do código. Aprenderemos a utilizar a palavra reservada event e delegate. Veremos como o computador realiza inferência para facilitar o nosso trabalho de desenvolvimento.

Também entraremos em contato com alguns recursos do C#, verificando como o compilador pode nos ajudar com todas essas tarefas. Todo o curso é regado de boas práticas e convenções, que são fundamentais para nos desenvolvermos um projeto de qualidade como profissionais qualificados.

Talvez você esteja acostumado com projetos WPF ou Windows Forms, em que simplesmente arrastamos um botão para a área de trabalho, e ao darmos um duplo clique sobre ele, somos automaticamente direcionados para o Visual Studio, e é criado um método que possui argumentos e toda uma construção já bem definida.

Área de trabalho do WPF, exibindo um botão que foi diretamente arrastado do painel de ferramentas

Aprenderemos como isso funciona "por debaixo dos panos", isto é, entender como o Visual Studio cria esses itens, e como eles operam da forma como estamos acostumados.

Nosso projeto será do cliente Bytebank, trata-se de uma lista de agências do banco que será utilizada para facilitar o trabalho de atendentes. Trata-se de um projeto de escopo pequeno, com validação de campos e, claro, uma lista em que um item pode ser selecionado e atualizado.

Conheceremos a importância desses recursos em um projeto pequeno, e saberemos como utilizá-los em projetos maiores que encontraremos ao longo de nossas carreiras.

Vamos lá?

Comportamentos e Eventos - Nosso projeto inicial

Começaremos o projeto do nosso cliente, o banco Bytebank. Precisamos criar uma aplicação para listar todas as agências do banco. Temos um modelo da tela a ser criada durante o curso, que conterá uma lista de agências à esquerda, e um painel à direita que conterá as propriedades detalhadas de cada agência. O que esperamos da usabilidade dessa aplicação é que o usuário possa marcar uma agência na lista, o painel de detalhes será atualizado e serão disponibilizadas as opções de "Editar" e "Apagar". Nossa aplicação será usada pelos funcionários do banco.

Painel de modelo que contém cinco agências listadas.Na, está selecionada a agência "0484 -Agencia Paulista". À direita são exibidos os detalhes dessa agência, que são "Número", "Nome", "Telefone", "Descrição" e "Endereço". Por fim, são exibidos dois botões de "Editar" e "Apagar"

No Visual Studio, já temos a solução de "ponta-pé" inicial. Começaremos com dois projetos: ByteBank.Agencias e ByteBank.Agencias.DAL, sendo que .DAL É a camada de acesso aos dados. Dentro de ByteBank.DAL teremos o arquivo ByteBank.mdf de banco de dados, e o ByteBankModel.edmx que corresponde ao mapeamento do Entity Framework para o banco de dados, essas são ferramentas que estão utilizando o curso que não precisamos entender em profundidade, mas na Alura temos o curso de Entity, caso você queira estudar mais essa tecnologia.

Para montarmos a tela da aplicação, criamos um projeto WPF no Visual Studio. Para fazer isso, basta abrir uma nova instância do Visual Studio, selecionar "File > New > Project" e teremos a opção "WPF App" ou "WPF Application", dependendo da versão do Visual Studio. Não fizemos nenhum tipo de modificação na aplicação WPF, construiremos tudo juntos. Lembrando que não é necessário conhecer WPF para darmos andamento ao projeto.

O arquivo MainWindow.xaml possui uma marcação para juntar os controles na tela, muito semelhante ao XML. Termos uma tag <Window>, que representa a janela de formulário do usuário.

<Window x:Class="ByteBank.Agencias.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:ByteBank.Agencias"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>

    </Grid> 
</Window>

Exibiremos o design desse código: clicaremos com o botão direito e selecionaremos a opção "View Designer", e começaremos a estruturar a nossa aplicação.

Área de trabalho do Visual Studio. A tela está dividida em duas formas de visualização: a primeira apresenta o código do design, e a segunda o design em si de uma caixa janela de formulário

Primeiramente precisaremos inserir uma lista à esquerda e o painel de detalhes à direita, começaremos pela segunda opção. Usaremos o elemento <StackPanel>, trata-se de um painel em que iremos inserir itens que vão sendo empilhados um sobre os outros. Em seguida, criaremos um elemento para mostrar os títulos em negrito(Bold) das propriedades, isto é, "Número", "Nome", "Telefone" e assim por diante, em seguida inseriremos os valores que não estarão em negrito.

    <Grid>
        <StackPanel>
            <TextBlock FontWeight="Bold">Número</TextBlock>
            <TextBlock >Número"></TextBlock>
            <TextBlock FontWeight="Bold">Nome</TextBlock>
            <TextBlock >Nome"></TextBlock>
            <TextBlock FontWeight="Bold">Telefone</TextBlock>
            <TextBlock >Telefone"></TextBlock>
            <TextBlock FontWeight="Bold">Descrição</TextBlock>
            <TextBlock >Descricao"></TextBlock>
            <TextBlock FontWeight="Bold">Endereço</TextBlock>
            <TextBlock >Endereco"></TextBlock>
        </StackPanel>

    </Grid> 

Em seguida, modificaremos o elemento <Grid> para <Canvas>, pois ele permite que posicionemos os itens na tela de uma forma mais simples. Declararemos, ainda, que Canvas.Top é igual a 15 pixels, ou seja, a posição superior do meu objeto será de 15 pixels. Faremos o mesmo para a esquerda, isto é Canvas.Left, mas com o valor de 290 pixels. Feito isso, adicionaremos o atributo Name, e adicionaremos txt valor dos campos, por exemplo: Name=txtEndereco.

    <Canvas>

        <StackPanel Canvas.Top="15" Canvas.Left="290">
            <TextBlock FontWeight="Bold">Número</TextBlock>
            <TextBlock Name="txtNumero"></TextBlock>
            <TextBlock FontWeight="Bold">Nome</TextBlock>
            <TextBlock Name="txtNome"></TextBlock>
            <TextBlock FontWeight="Bold">Telefone</TextBlock>
            <TextBlock Name="txtTelefone"></TextBlock>
            <TextBlock FontWeight="Bold">Descrição</TextBlock>
            <TextBlock Name="txtDescricao"></TextBlock>
            <TextBlock FontWeight="Bold">Endereço</TextBlock>
            <TextBlock Name="txtEndereco"></TextBlock>
        </StackPanel>

    </Canvas> 

Ao observarmos a construção no design, perceberemos que apenas os título estarão visíveis, afinal, os valores serão preenchidos dinamicamente conforme a lista de agências. Para criarmos a lista, usaremos o elemento <ListBox>, que terá uma largura(Width) de 270 e altura(Height) de 290. Por fim, alinharemos os ele,elementos no <Canvas>, posicionando-os à direita e à esquerda em 15 pixels.

    <Canvas>

        <ListBox Width="290" Height="290">
            Canvas.Top="15"
            Cavans.Left="15"</ListBox>

        <StackPanel Canvas.Top="15" Canvas.Left="290">
            <TextBlock FontWeight="Bold">Número</TextBlock>
            <TextBlock Name="txtNumero"></TextBlock>
            <TextBlock FontWeight="Bold">Nome</TextBlock>
            <TextBlock Name="txtNome"></TextBlock>
            <TextBlock FontWeight="Bold">Telefone</TextBlock>
            <TextBlock Name="txtTelefone"></TextBlock>
            <TextBlock FontWeight="Bold">Descrição</TextBlock>
            <TextBlock Name="txtDescricao"></TextBlock>
            <TextBlock FontWeight="Bold">Endereço</TextBlock>
            <TextBlock Name="txtEndereco"></TextBlock>
        </StackPanel>

    </Canvas> 

Executaremos o código e veremos que a janela de formulário está bem próxima ao modelo que apresentamos no começo da aula, resta ainda os botões "Editar" e "Apagar", que inseriremos posteriormente. O próximo passo é popular a lista.

janela de formulário com as propriedades "Número", "Nome", "Telefone", "Descrição" e "Endereço" posicionadas à direta. À esquerda, quadrado vazio que abrigará a lista de agências

Abriremos o arquivo MainWindow.xaml.cs:


namespace ByteBank.Agencias
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            IntializeComponent();
        }
    }
}

Primeiramente, precisaremos construir uma conexão com o banco de dados, logo, criaremos um campo privado. No projeto ByteBank.Agencias.DAL, já foi criado o mapeamento, seu nome é ByteBankEntities. Utilizaremos o atalho "Ctrl + ." para adicionar a diretiva using do Visual Studio, que chamaremos de contextoBancoDeDados. Criaremos uma nova instância para guardar nosso campo, e segundo uma boa prática, será um campo privado de somente leitura (readonly). Adicionaremos ainda um underline (_) no inicio do nome do campo para seguirmos a convenção de nomeação de campos privados _contextoBancoDeDados.

namespace ByteBank.Agencias
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

            private readonly ByteBankEntities _contextoBancoDeDados = new ByteBankEntities(); 

        public MainWindow()
        {
            IntializeComponent();
        }
    }
}

Teremos o construtor da janela principal (MainWindow()), que chama o método IntializeComponent() que foi implementado no começo do projeto pelo Visual Studio. Depois dessa chamada, evocaremos o método AtualizarControles(), que será responsável por atualizar os itens da tela. O Visual Studio apontara erro nesse método, afinal ele ainda não foi implementado. Criaremos, então, um campo privado chamado AtualizarControles().

namespace ByteBank.Agencias
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {

            private readonly ByteBankEntities _contextoBancoDeDados = new ByteBankEntities(); 

        public MainWindow()
        {
            IntializeComponent();

            AtualizarControles();
        }

        private void AtualizarControles()
        {

        }
    }
}

Em MainWindow.xaml, daremos um nome para a nossa lista, que será lstAgencias

<ListBox Width="270"
         Height="290"
         Canvas.Top="15"
         Canvas.Left="15"
         Name="lstAgencias">
</ListBox>

De volta para MainWindow.xaml.cs, adicionaremos o nome da lista no campo privado. Teremos acessoa a uma propriedade da <ListBox> chamada items, que nos permite adicionar itens à lista. Devemos adicionar as agências que serão recuperadas do contexto do banco de dados, portanto criaremos uma variável para guardar as agências, cujo nome será agencias. Em seguida, chamaremos o método ToList().

Agora podemos "inteirar" por essas agências: para cada agencia em nossa coleção de agencias, iremos adicionar em nossa lista, logo lstAgencias.Items, e usaremos o método Add() que receberá como parâmetro agencia.


        public MainWindow()
        {
            IntializeComponent();

            AtualizarControles();
        }

        private void AtualizarControles()
        {
            var agencias = _contextoBancoDeDados.Agencias.ToList(); 
            foreach (var agencia in agencias)
                lstAgencias.Items.Add(agencia);
        }
    }
}

Para prevenir que esse esse método não será duplicado, limparemos a lista de agencias e depois a preencheremos novamente, assim, se chamamos o método por engando duas vezes seguidas, não teremos problemas com os elementos. Escreveremos lstAgencias.Items.Clear() para que possamos limpar a coleção de itens em nossa lista.


        public MainWindow()
        {
            IntializeComponent();

            AtualizarControles();
        }

        private void AtualizarControles()
        {
            lstAgencias.Items.Clear():
            var agencias = _contextoBancoDeDados.Agencias.ToList(); 
            foreach (var agencia in agencias)
                lstAgencias.Items.Add(agencia);
        }
    }
}

Executaremos a aplicação e ao acessarmos a janela, veremos que no espaço que deveria ser exibido o número da agência teremos o nome completo da classe Agencia sendo exibido: ByteBank.Agencias.DALA.Agencia. Isso acontece porque estamos enviando um objeto complexo para uma lista que espera receber simplesmente um texto. Iremos melhorar esse ponto para chegarmos em um resultado mais satisfatório.

Para isso, precisaremos mudar a forma como Agencia é transformada em uma string. Pausaremos a aplicação, e em MainWindow.xaml.cs selecionaremos o termo Agencia, que está ao lado de _contextoBancoDeDados, e pressionaremos a tecla "F12". Seremos direcionados para a definição do membro selecionado na tela de edição.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Agencia> Agencias { get; set; }

Em seguida, iremos selecionar Agencia de DbSet<Agencia>, e pressionar novamente o atalho "F12". Desse modo acessaremos a classe gerada pelo Entity Framework:

namespace ByteBank.Agencias.DAL
{
    using Sytem;
    using System.Collections.Generic;

    public partial class Agencia 
    {
        public string Numero { get; set; } 
        public string Nome { get; set } 
        public string Descricao { get; set; }
        public string Endereco { get; set; }
        public string Telefone { get; set; }

Não é uma boa prática alterar uma classe gerada pelo Visual Studio, mas como ela é uma classe parcial, isto é, uma classe que pode conter parte de sua definição em vários arquivos diferentes, continuaremos sua extensão em um novo arquivo. Em ByteBank.Agencias.DAL, criaremos uma nova classe chamada AgenciaMetodos.cs.

namespace ByteBank.Agencias.DAL
{
    class AgenciaMetodos
    {
    }
} 

Essa classe será a continuação da classe parcial criada pelo Visual Studio, portanto escreveremos public partial class Agencia.

namespace ByteBank.Agencias.DAL
{
    public partial class Agencia
    {
    }
} 

Se "classe parcial" não é uma definição muito clara para você, expliquemos novamente: trata-se de uma classe em que é possível armazenar sua definição em vários arquivos diferentes. Criaremos uma classe de exemplo para entendermos melhor essa questão:

namespace ByteBank.Agencias.DAL
{
    public class ClasseExemplo
    {
    }
}

Estamos acostumados a criar uma classe pública(public) como no exemplo acima, e quando fazemos desse modo precisamos definir todas as propriedades, campos e métodos dentro de um único arquivo. Se temos uma classe muito grande e queremos separar arquivos diferentes para métodos e propriedades, isso não será possível. Dessa impossibilidade, nasceu a ideia de classe parcial, para isso, basta simplesmente adicionar a palavra reservada partial em nossa definição.

namespace ByteBank.Agencias.DAL
{
    public class partial ClasseExemplo
    {
    }
}

Ao inserirmos o partial na definição de classe, poderemos ter o arquivo ClasseExemplo.cs, outro como CasseExempoMetodos.cs e continuar escrevendo métodos específicos dessa casse. Quando o Visual Studio compilar nosso código, todos os arquivos que possuem a definição parcial serão lidos e unificados, como um arquivo só. Esse recurso torna a leitura e criação de código muito mais fácil.

É muito útil usar classes parciais quando estamos lindando com o Entity, já que ele cria dinamicamente arquivos. Não podemos alterar arquivos gerados automaticamente pelo Visual Studio, pois caso aconteça um reprocessamento, tudo será apagado e refeito e os métodos serão perdidos.

De volta a classe Agencia, queremos mudar a forma em que ela é transformada em uma string, para melhorar a nossa visualização na lista. Temos um método conhecido como ToString(), proveniente da classe Object, e o sobrescreveremos.

namespace ByteBank.Agencias.DAL
{
    public partial class Agencia
    {
        public override string ToString()
    }
}

Usaremos recursos do C# 6 para montar um retorno somente em uma linha. Usaremos interpolação de string para declarar que teremos Numero, seguido do nosso Nome.

namespace ByteBank.Agencias.DAL
{
    public partial class Agencia
    {
        public override string ToString() =>
            ${Numero} - {Nome}";
    }
}

Ao executarmos novamente a aplicação, teremos um resultado muito melhor e a lista é apresentada em um formato legível. Contudo, a barra de rolagem ou scroll bar está muito grande, isso ocorre porque Nome possui vários espaços vazios.

janela de formulário com a lista de agências sendo exibida no formato nome e numero à esquerda, como"0484 - Agência Carioca",primeiro item da lista. A direita da janela as propriedades vazias "Número", "Nome", "Telefone", "Descrição" e "Endereço". Na parte inferior da janela, a barra de rolagem que corresponde a lista de agências está muito maior que o necessário.

Para resolver esse problema, no momento de fazer ToString(), isto é, a conversão para string, chamaremos o método Trim() que corta espaços vazios de uma string, preservando seu conteúdo.

namespace ByteBank.Agencias.DAL
{
    public partial class Agencia
    {
        public override string ToString() =>
            ${Numero} - {Nome}".Trim();
    }
}

A barra de rolagem sumirá da janela. Ao clicarmos em uma agência qualquer para editarmos suas propriedades, veremos que esses campos ficam vazios. Nosso próximo passo é escrever o código que fará com que os detalhes de cada agência surjam cada vez que cliquemos sobre elas.

Comportamentos e Eventos - Comportamento em nossos elementos

No momento em que clicamos em uma agência da lista, queremos que os os valores de texto do painel de detalhes seja atualizado. Precisamos implementar esse comportamento em nossa aplicação. A forma tradicional de modificar comportamento de classe é trabalhar com herança: criamos uma classe filha, herda a classe mãe e muda seu comportamento a partir da classe filha. Podemos realizar o esse procedimento com os controles do formulário, e aparentemente é esse caminho que precisaremos seguir no projeto; herdaremos a ListBox e sobrescreveremos o método que atua quando mudamos a agência selecionada, parecido com o que fizemos em Agencia ao sobrescrevermos o método ToString() para modificar o comportamento de como essa classe é convertida para string.

namespace ByteBank.Agencias.DAL
{
    public partial class Agencia
    {
        public override string ToString() =>
            $"{Numero} - {Nome}".Trim();
    }

}

Na área "Solution Explorer", clicaremos sobre ByteBank.Agencias criaremos uma nova classe chamada AgenciasListBox. Essa classe será pública e herdará a classe ListBox. Acionaremos o atalho "Ctrl + ." para adicionar a diretiva using System.Windows.Controls.

namespace ByteBank.Agencias
{
    public class AgenciasListBox : ListBox
    {
    }
}

Quando mudamos o item selecionado da lista de agências, os campos da janela mãe "Número","Nome","Telefone","Descrição" e "Endereço" devem ser atualizados, portanto nós possuímos uma dependência da janela mãe. Adicionaremos essa dependência no construtor - que ainda precisa ser criado - da classe AgenciasListBox. Usaremos o code snippet ctor do Visual Studio e pressionaremos "Tab" para que o código do construtor seja gerado.

namespace ByteBank.Agencias
{
    public class AgenciasListBox : ListBox
    {
        public AgenciasListBox()
        {
        }
    }
}

Já definimos que a dependência da nossa lista é saber qual é a janela mãe da aplicação. A janela mãe se chama MainWindow, trata-se da janela criada por padrão em todo projeto WPF. Chamaremos a MainWindowde janelaMae, por fim guardaremos essas informações dentro de um campo privado apenas de leitura.

namespace ByteBank.Agencias
{
    public class AgenciasListBox : ListBox
    {
        private readonly MainWindow _janelaMae;

        public AgenciasListBox(MainWindow janelaMae)
        {
            _janelaMae = janelaMae
        }
    }
}

janelaMae é um parâmetro obrigatório do construtor, portanto se ele for nulo, lançaremos uma exceção de ArgumentNullException(). Em seguida, precisaremos sobrescrever o método de seleção para atualizar os campos da janela. Escreveremos override, e o Visual Studio exibe quais são as possibilidades de método a serem utilizadas, em nosso caso, usaremos OnSelectionChanged().

namespace ByteBank.Agencias
{
    public class AgenciasListBox : ListBox
    {
        private readonly MainWindow _janelaMae;

        public AgenciasListBox(MainWindow janelaMae)
        {
            _janelaMae = janelaMae ?? throw new ArgumentNullException(nameoff(janelaMae));
        }

        protected override void OnSelectionChanged(SelectionChangedEventsArgs e)
        {
            base.OnSelectionChanged(e);
        }
    }
}

Manteremos o base.OnSelectionChanged(), pois trata-se da chamada do método original da classe, e adiante escreveremos o código específico da ListBox. Primeiramente, recuperaremos o item selecionado, portanto var agenciaSelecionada será igual a propriedade SelectedItem da ListBox, que indica qual item foi selecionado. Ao pressionarmos "F12" com esse propriedade selecionada, descobriremos que se trata de um objeto, e nesse caso precisaremos realizar um cast para transformar esse tipo em Agencia. Por fim, adicionaremos a diretiva using.

namespace ByteBank.Agencias
{
    public class AgenciasListBox : ListBox
    {
        private readonly MainWindow _janelaMae;

        public AgenciasListBox(MainWindow janelaMae)
        {
            _janelaMae = janelaMae ?? throw new ArgumentNullException(nameoff(janelaMae));
        }

        protected override void OnSelectionChanged(SelectionChangedEventsArgs e)
        {
            base.OnSelectionChanged(e);

            var agenciaSelecionada = (Agencia)SelectedItem;
        }
    }
}

Desse modo, poderemos atualizar os campos da janela mãe. O primeiro deles será txtNumero.Text, que será igual à agenciaSelecionada.Numero. Seguiremos o mesmo padrão para todos os detalhes da agência.


        protected override void OnSelectionChanged(SelectionChangedEventsArgs e)
        {
            base.OnSelectionChanged(e);

            var agenciaSelecionada = (Agencia)SelectedItem;

            _janelaMae.txtNumero.Text = agenciaSelecionada.Numero;
            _janelaMae.txtNome.Text = agenciaSelecionada.Nome;
            _janelaMae.txtTelefone.Text = agenciaSelecionada.Telefone;
            _janelaMae.txtEndereco.Text = agenciaSelecionada.Endereco;
            _janelaMae.txtDescricao.Text = agenciaSelecionada.Descricao;
        }
    }
}

Agora que criamos a ListBox, precisamos usá-la na janela principal. Não usaremos mais a definição xml do WPF, portanto em MainWindow.xaml retiraremos o seguinte trecho de código (a list box do .NET):

<ListBox Width="270"
         Height="290"
         Canvas.Top="15"
         Canvas.Left="15"
         Name="lstAgencias">
</ListBox>

Criaremos essa lista no arquivo de forma programática em MainWindow.xaml.cs. Faremos uma nova instância de AgenciasListBox, que chamaremos de lstAgencias e para manter o código de AtualizarControles(), passaremos AgenciasListBox() e this para criar a instância.

private readonly ByteBankEntities _contextoBancoDeDados = new ByteBankEntities();
private readonly AgenciasListBox lstAgencias = new AgenciasListBox(this);

public MainWindow()
{
    InitializeComponent();

    AtualizarControles();
}

Porém, há um problema: não podemos usar o this quando estamos criando um campo, portanto escreveremos AgenciasListBox(this) no construtor.

private readonly ByteBankEntities _contextoBancoDeDados = new ByteBankEntities();
private readonly AgenciasListBox lstAgencias;

public MainWindow()
{
    InitializeComponent();

    lsAgencias = new AgenciasListBox(this);
    AtualizarControles();
}

Como foi dito, o código de AtualizarControles() se mantém, mas precisaremos atualizar alguns campos de lstAgencias para serem exibidos na tela. Em MainWindow.xaml temos o elementos <Canvas> que não havia sido nomeado. Colocaremos o nome de container, afinal ele conterá todos os elementos da janela.

<Canvas Name="container">
        <StackPanel Canvas.Top="15" Canvas.Left="290">
            <TextBlock FontWeight="Bold">Número</TextBlock>
            <TextBlock Name="txtNumero"></TextBlock>
            <TextBlock FontWeight="Bold">Nome</TextBlock>
            <TextBlock Name="txtNome"></TextBlock>
            <TextBlock FontWeight="Bold">Telefone</TextBlock>
            <TextBlock Name="txtTelefone"></TextBlock>
            <TextBlock FontWeight="Bold">Descrição</TextBlock>
            <TextBlock Name="txtDescricao"></TextBlock>
            <TextBlock FontWeight="Bold">Endereço</TextBlock>
            <TextBlock Name="txtEndereco"></TextBlock>
        </StackPanel>

</Canvas>

De volta a MainWindow.xaml.cs, escreveremos que container terá vários filhos (Children) que serão controles da nossa janela. Em seguida, adicionaremos (Add()) lstAgencias. Tudo isso porque queremos adicionar uma funcionalidade para o evento de clicar na lista e atualizar os detalhes de cada agência.

private void AtualizarControles()
{
    container.Children.Add(lstAgencias);

    lstAgencias.Items.Clear();
    var agencias = _contextoBancoDeDados.Agencias.ToList();
    foreach (var agencia in agencias)
        lstAgencias.Items.Add(agencia);
}

Adicionamos a lista, mas ainda não definimos sua altura e largura, e precisamos fazê-lo: a largura(Width) terá o valor de 270 e altura(Height) terá o valor de 290. Em seguida, precisaremos definir a relação que a lista possui com Canvas, isto é, a margem superior e a margem da esquerda, logo: Canvas.SetTop(lstAgencias, 15), isto é, o elemento lstAgencias mais o offset 15. Faremos o mesmo procedimento para definir a distancia à esquerda SetLeft.

private void AtualizarControles()
{

    lstAgencias.Width = 270;
    lstAgencias.Height = 290;

    Canvas.SetTop(lstAgencias, 15);
    Canvas.SetLeft(lstAgencias, 15);
    container.Children.Add(lstAgencias);

    lstAgencias.Items.Clear();
    var agencias = _contextoBancoDeDados.Agencias.ToList();
    foreach (var agencia in agencias)
        lstAgencias.Items.Add(agencia);
}

Executaremos a aplicação. Na janela de formulário, ao navegarmos por diferentes agências, os campos de detalhe são atualizados, isto é, conseguimos atribuir uma funcionalidade para o evento de clique.

 janela com lista de agencias, com a agencia "4420 - Agencia Paulista" selecionada. Ao lado direito detalhes sobre ela são exibidos por via dos campos "Número:4420", "Nome:Agência Paulista", "Telefone:(45)9 1123 4456", "Descrição:Agência para pessoa física" e "Endereço: Avenida Paulista XYZ"

Resta agora inserir os botões "Editar" e "Excluir", o que faremos nas próximas aulas. Vamos lá?

Sobre o curso C#: Eventos, Delegates e Lambda

O curso C#: Eventos, Delegates e Lambda possui 195 minutos de vídeos, em um total de 50 atividades. Gostou? Conheça nossos outros cursos de .NET em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda .NET acessando integralmente esse e outros cursos, comece hoje!

  • 1017 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 1017 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 1017 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 1017 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?
Acesso por 1 ano
Estude 24h/dia onde e quando quiser
Novos cursos toda semana