Compartilhar via


Tutorial: Criar um aplicativo de banco de dados de clientes

Este tutorial cria um aplicativo simples para gerenciar uma lista de clientes. Ao fazer isso, ele introduz uma seleção de conceitos básicos para aplicativos empresariais na UWP. Você aprenderá a:

  • Implemente as operações Criar, Ler, Atualizar e Excluir em um banco de dados SQL local.
  • Adicione uma grade de dados para exibir e editar dados do cliente em sua interface do usuário.
  • Organize os elementos da interface do usuário juntos em um layout de formulário básico.

O ponto de partida deste tutorial é um aplicativo de página única com interface do usuário e funcionalidade mínimas, com base em uma versão simplificada do aplicativo de exemplo de banco de dados de pedidos de clientes. Ele foi criado em C# e XAML, e esperamos que você tenha uma familiaridade básica com essas duas linguagens.

A página principal do aplicativo de trabalho

Pré-requisitos

Após ter clonado/baixado o repositório, você poderá editar o projeto abrindo o CustomerDatabaseTutorial.sln com o Visual Studio.

Observação

Este tutorial é baseado no exemplo de banco de dados de pedidos de clientes que foi atualizado recentemente para usar o WinUI e o SDK do Aplicativo Windows. Até que este tutorial e código sejam atualizados, haverá diferenças entre os dois exemplos.

Parte 1: Código de Interesse

Se você executar o aplicativo imediatamente após abri-lo, verá alguns botões na parte superior de uma tela em branco. Embora não seja visível para você, o aplicativo já inclui um banco de dados SQLite local provisionado com alguns clientes de teste. A partir daqui, você começará implementando um controle de interface do usuário para exibir esses clientes e, em seguida, passará para a adição de operações no banco de dados. Antes de começar, veja onde você vai trabalhar.

Exibições

CustomerListPage.xaml é a exibição do aplicativo, que define a interface do usuário para a página única neste tutorial. Sempre que você precisar adicionar ou alterar um elemento visual na interface do usuário, isso será feito neste arquivo. Este tutorial fornece um passo a passo da adição destes elementos:

  • Um RadDataGrid para exibir e editar seus clientes.
  • Um StackPanel para definir os valores iniciais para um novo cliente.

ViewModels

ViewModels\CustomerListPageViewModel.cs é onde a lógica fundamental do aplicativo está localizada. Cada ação do usuário executada na exibição será passada para este arquivo para processamento. Neste tutorial, você adicionará um novo código e implementará os seguintes métodos:

  • CreateNewCustomerAsync, que inicializa um novo objeto CustomerViewModel.
  • DeleteNewCustomerAsync, que remove um novo cliente antes que ele seja exibido na interface do usuário.
  • DeleteAndUpdateAsync, que manipula a lógica do botão de exclusão.
  • GetCustomerListAsync, que recupera uma lista de clientes do banco de dados.
  • SaveInitialChangesAsync, que adiciona as informações de um novo cliente ao banco de dados.
  • UpdateCustomersAsync, que atualiza a interface do usuário para refletir quaisquer clientes adicionados ou excluídos.

CustomerViewModel é um wrapper para as informações de um cliente, que controla se ele foi ou não modificado recentemente. Você não precisará adicionar nada a essa classe, mas alguns dos códigos a serem adicionados em outro lugar farão referência a ela.

Para obter mais informações sobre como o exemplo é construído, confira a visão geral da estrutura de aplicativos.

Parte 2: Adicionar o DataGrid

Antes de começar a realizar operações nos dados do cliente, você precisará adicionar um controle de interface do usuário para exibir esses clientes. Para fazer isso, usaremos um controle RadDataGrid de terceiros. O pacote NuGet Telerik.UI.for.UniversalWindowsPlatform já foi incluído neste projeto. Vamos adicionar a grade ao nosso projeto.

  1. Abra Views\CustomerListPage.xaml no Gerenciador de Soluções. Adicione a seguinte linha de código dentro da tag Página para declarar um mapeamento para o namespace Telerik que contém a grade de dados.

        xmlns:telerikGrid="using:Telerik.UI.Xaml.Controls.Grid"
    
  2. Em CommandBar, em RelativePanel da Visualização, adicione um controle RadDataGrid com algumas opções básicas de configuração:

    <Grid
        x:Name="CustomerListRoot"
        Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <RelativePanel>
            <CommandBar
                x:Name="mainCommandBar"
                HorizontalAlignment="Stretch"
                Background="AliceBlue">
                <!--CommandBar content-->
            </CommandBar>
            <telerikGrid:RadDataGrid
                x:Name="DataGrid"
                BorderThickness="0"
                ColumnDataOperationsMode="Flyout"
                GridLinesVisibility="None"
                GroupPanelPosition="Left"
                RelativePanel.AlignLeftWithPanel="True"
                RelativePanel.AlignRightWithPanel="True"
                RelativePanel.Below="mainCommandBar" />
        </RelativePanel>
    </Grid>
    
  3. Você adicionou a grade de dados, mas ela precisa de dados para ser exibida. Adicione as seguintes linhas de código a ela:

    ItemsSource="{x:Bind ViewModel.Customers}"
    UserEditMode="Inline"
    

    Agora que você definiu uma fonte de dados a ser exibida, RadDataGrid manipulará a maior parte da lógica da interface do usuário para você. No entanto, se você executar seu projeto, ainda não verá nenhum dado em exibição. Isso porque o ViewModel ainda não está carregando.

Aplicativo em branco, sem clientes

Parte 3: Ler clientes

Quando é inicializado, ViewModels\CustomerListPageViewModel.cs chama o método GetCustomerListAsync. Esse método precisa recuperar os dados de cliente de teste do banco de dados SQLite incluído no tutorial.

  1. Em ViewModels\CustomerListPageViewModel.cs, atualize o método GetCustomerListAsync com este código:

    public async Task GetCustomerListAsync()
    {
        var customers = await App.Repository.Customers.GetAsync(); 
        if (customers == null)
        {
            return;
        }
        await DispatcherHelper.ExecuteOnUIThreadAsync(() =>
        {
            Customers.Clear();
            foreach (var c in customers)
            {
                Customers.Add(new CustomerViewModel(c));
            }
        });
    }
    

    O método GetCustomerListAsync é chamado quando o ViewModel é carregado, mas antes desta etapa, ele não fazia nada. Aqui, adicionamos uma chamada ao método GetAsync no Repository/SqlCustomerRepository. Isso permite que ele entre em contato com o repositório para recuperar uma coleção enumerável de objetos Customer. Em seguida, ele os analisa em objetos individuais antes de adicioná-los à ObservableCollection interna para que possam ser exibidos e editados.

  2. Execute seu aplicativo. Agora você verá a grade de dados exibindo a lista de clientes.

Lista inicial de clientes

Parte 4: Editar clientes

Você pode editar as entradas na grade de dados clicando duas vezes nelas, mas precisa garantir que todas as alterações feitas na interface do usuário também sejam feitas em sua coleção de clientes no code-behind. Isso significa que você terá que implementar a vinculação de dados bidirecional. Se você quiser mais informações sobre isso, confira nossa introdução à vinculação de dados.

  1. Primeiro, declare que ViewModels\CustomerListPageViewModel.cs implementa a interface INotifyPropertyChanged:

    public class CustomerListPageViewModel : INotifyPropertyChanged
    
  2. Em seguida, no corpo principal da classe, adicione o seguinte evento e método:

    public event PropertyChangedEventHandler PropertyChanged;
    
    public void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    

    Com o método OnPropertyChanged, fica mais fácil para os setters chamar o evento PropertyChanged, que é necessário para a vinculação de dados bidirecional.

  3. Atualize o setter para SelectedCustomer com esta chamada de função:

    public CustomerViewModel SelectedCustomer
    {
        get => _selectedCustomer;
        set
        {
            if (_selectedCustomer != value)
            {
                _selectedCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  4. Em Views\CustomerListPage.xaml, adicione a propriedade SelectedCustomer à grade de dados.

    SelectedItem="{x:Bind ViewModel.SelectedCustomer, Mode=TwoWay}"
    

    Isso associa a seleção do usuário na grade de dados com o objeto Customer correspondente no code-behind. O modo de vinculação bidirecional permite que as alterações feitas na interface do usuário sejam refletidas nesse objeto.

  5. Execute seu aplicativo. Agora você pode ver os clientes exibidos na grade e fazer alterações nos dados subjacentes por meio da interface do usuário.

Como editar um cliente na grade de dados

Parte 5: Atualizar clientes

Agora que você pode ver e editar seus clientes, precisará ser capaz de enviar suas alterações para o banco de dados e extrair quaisquer atualizações que tenham sido feitas por outras pessoas.

  1. Retorne para ViewModels\CustomerListPageViewModel.cs e navegue até o método UpdateCustomersAsync. Atualize-o com este código para enviar alterações por push para o banco de dados e recuperar novas informações:

    public async Task UpdateCustomersAsync()
    {
        foreach (var modifiedCustomer in Customers
            .Where(x => x.IsModified).Select(x => x.Model))
        {
            await App.Repository.Customers.UpsertAsync(modifiedCustomer);
        }
        await GetCustomerListAsync();
    }
    

    Esse código utiliza a propriedade IsModified de ViewModels\CustomerViewModel.cs, que é atualizada automaticamente sempre que o cliente é alterado. Isso permite que você evite chamadas desnecessárias e envie apenas alterações de clientes atualizados para o banco de dados.

Parte 6: Criar um cliente

Adicionar um novo cliente representa um desafio, pois o cliente aparecerá como uma linha em branco se você adicioná-lo à interface do usuário antes de fornecer valores para suas propriedades. Isso não é um problema, mas aqui vamos facilitar a definição dos valores iniciais de um cliente. Neste tutorial, adicionaremos um painel recolhível simples, mas se você tivesse mais informações para adicionar, poderia criar uma página separada para essa finalidade.

Atualizar o code-behind

  1. Adicione um novo campo privado e uma nova propriedade pública a ViewModels\CustomerListPageViewModel.cs. Isso será usado para controlar se o painel está visível ou não.

    private bool _addingNewCustomer = false;
    
    public bool AddingNewCustomer
    {
        get => _addingNewCustomer;
        set
        {
            if (_addingNewCustomer != value)
            {
                _addingNewCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  2. Adicione uma nova propriedade pública ao ViewModel, um inverso do valor de AddingNewCustomer. Isso será usado para desativar os botões regulares da barra de comandos quando o painel estiver visível.

    public bool EnableCommandBar => !AddingNewCustomer;
    

    Agora você precisará de uma maneira de exibir o painel recolhível e criar um cliente para editar nele.

  3. Adicione uma nova propriedade privada e pública ao ViewModel para manter o cliente recém-criado.

    private CustomerViewModel _newCustomer;
    
    public CustomerViewModel NewCustomer
    {
        get => _newCustomer;
        set
        {
            if (_newCustomer != value)
            {
                _newCustomer = value;
                OnPropertyChanged();
            }
        }
    }
    
  4. Atualize o método CreateNewCustomerAsync para criar um cliente, adicioná-lo ao repositório e defini-lo como o cliente selecionado:

    public async Task CreateNewCustomerAsync()
    {
        CustomerViewModel newCustomer = new CustomerViewModel(new Models.Customer());
        NewCustomer = newCustomer;
        await App.Repository.Customers.UpsertAsync(NewCustomer.Model);
        AddingNewCustomer = true;
    }
    
  5. Atualize o método SaveInitialChangesAsync para adicionar um cliente recém-criado ao repositório, atualizar a interface do usuário e fechar o painel.

    public async Task SaveInitialChangesAsync()
    {
        await App.Repository.Customers.UpsertAsync(NewCustomer.Model);
        await UpdateCustomersAsync();
        AddingNewCustomer = false;
    }
    
  6. Adicione a seguinte linha de código como a linha final no setter para AddingNewCustomer:

    OnPropertyChanged(nameof(EnableCommandBar));
    

    Isso garantirá que EnableCommandBar seja automaticamente atualizado sempre que AddingNewCustomer for alterado.

Atualizar a interface do usuário

  1. Navegue de volta para Views\CustomerListPage.xaml e adicione um StackPanel com as seguintes propriedades entre sua CommandBar e a grade de dados:

    <StackPanel
        x:Name="newCustomerPanel"
        Orientation="Horizontal"
        x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}"
        RelativePanel.Below="mainCommandBar">
    </StackPanel>
    

    O atributo x:Load garante que esse painel seja exibido somente quando você estiver adicionando um novo cliente.

  2. Faça a seguinte alteração na posição da grade de dados para garantir que ela se mova para baixo quando o novo painel for exibido:

    RelativePanel.Below="newCustomerPanel"
    
  3. Atualize o painel de pilha com quatro controles TextBox. Eles serão vinculados às propriedades individuais do novo cliente e permitirão que você edite seus valores antes da inclusão na grade de dados.

    <StackPanel
        x:Name="newCustomerPanel"
        Orientation="Horizontal"
        x:Load="{x:Bind ViewModel.AddingNewCustomer, Mode=OneWay}"
        RelativePanel.Below="mainCommandBar">
        <TextBox
            Header="First name"
            PlaceholderText="First"
            Margin="8,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.FirstName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Last name"
            PlaceholderText="Last"
            Margin="0,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.LastName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Address"
            PlaceholderText="1234 Address St, Redmond WA 00000"
            Margin="0,8,16,8"
            MinWidth="280"
            Text="{x:Bind ViewModel.NewCustomer.Address, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox
            Header="Company"
            PlaceholderText="Company"
            Margin="0,8,16,8"
            MinWidth="120"
            Text="{x:Bind ViewModel.NewCustomer.Company, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
    </StackPanel>
    
  4. Adicione um botão simples ao novo painel de pilha para salvar o cliente recém-criado:

    <StackPanel>
        <!--Text boxes from step 3-->
        <AppBarButton
            x:Name="SaveNewCustomer"
            Click="{x:Bind ViewModel.SaveInitialChangesAsync}"
            Icon="Save"/>
    </StackPanel>
    
  5. Atualize a CommandBar para que os botões regulares Criar, Excluir e Atualizar sejam desabilitados quando o painel de pilha estiver visível:

    <CommandBar
        x:Name="mainCommandBar"
        HorizontalAlignment="Stretch"
        IsEnabled="{x:Bind ViewModel.EnableCommandBar, Mode=OneWay}"
        Background="AliceBlue">
        <!--App bar buttons-->
    </CommandBar>
    
  6. Execute seu aplicativo. Agora você pode criar um cliente e inserir seus dados no painel de pilha.

Como criar um cliente

Parte 7: Excluir um cliente

A exclusão de um cliente é a operação básica final que você precisa implementar. Ao excluir um cliente selecionado na grade de dados, você deve chamar imediatamente UpdateCustomersAsync para atualizar a interface do usuário. No entanto, você não precisará chamar esse método se estiver excluindo um cliente que acabou de criar.

  1. Navegue até ViewModels\CustomerListPageViewModel.cs e atualize o método DeleteAndUpdateAsync:

    public async void DeleteAndUpdateAsync()
    {
        if (SelectedCustomer != null)
        {
            await App.Repository.Customers.DeleteAsync(_selectedCustomer.Model.Id);
        }
        await UpdateCustomersAsync();
    }
    
  2. Em Views\CustomerListPage.xaml, atualize o painel de pilha para adicionar um novo cliente para que ele contenha um segundo botão:

    <StackPanel>
        <!--Text boxes for adding a new customer-->
        <AppBarButton
            x:Name="DeleteNewCustomer"
            Click="{x:Bind ViewModel.DeleteNewCustomerAsync}"
            Icon="Cancel"/>
        <AppBarButton
            x:Name="SaveNewCustomer"
            Click="{x:Bind ViewModel.SaveInitialChangesAsync}"
            Icon="Save"/>
    </StackPanel>
    
  3. Em ViewModels\CustomerListPageViewModel.cs, atualize o método DeleteNewCustomerAsync para excluir o novo cliente:

    public async Task DeleteNewCustomerAsync()
    {
        if (NewCustomer != null)
        {
            await App.Repository.Customers.DeleteAsync(_newCustomer.Model.Id);
            AddingNewCustomer = false;
        }
    }
    
  4. Execute seu aplicativo. Agora você pode excluir clientes, seja dentro da grade de dados ou no painel de pilha.

Excluir um novo cliente

Conclusão

Parabéns! Com tudo isso feito, seu aplicativo agora tem uma gama completa de operações de banco de dados local. Você pode criar, ler, atualizar e excluir clientes em sua interface do usuário, e essas alterações serão salvas no banco de dados e persistirão em diferentes inicializações do aplicativo.

Agora que você terminou, considere o seguinte:

Ou, caso esteja pronto para um desafio, siga em frente...

Indo além: conecte-se a um banco de dados remoto

Fornecemos um passo a passo de como implementar essas chamadas em um banco de dados SQLite local. Mas e se você quiser usar um banco de dados remoto em vez disso?

Se você quiser fazer uma tentativa, precisará de sua própria conta do Azure Active Directory (AAD) e da capacidade de hospedar sua própria fonte de dados.

Você precisará adicionar autenticação, funções para lidar com chamadas REST e, em seguida, criar um banco de dados remoto para interagir. Há um código no exemplo de banco de dados de pedidos de clientes completo que você pode consultar em cada operação necessária.

Definições e configuração

As etapas necessárias para se conectar ao seu próprio banco de dados remoto estão descritas no Leiame do exemplo. Será necessário fazer o seguinte:

  • Forneça a ID do cliente da sua conta do Azure para Constants.cs.
  • Forneça a URL do banco de dados remoto para Constants.cs.
  • Forneça a cadeia de conexão para o banco de dados para Constants.cs.
  • Associar seu aplicativo à Microsoft Store.
  • Copie o projeto de serviço no aplicativo e implante-o no Azure.

Autenticação

Você precisará criar um botão para iniciar uma sequência de autenticação e um pop-up ou uma página separada para coletar as informações de um usuário. Depois de criá-lo, você precisará fornecer um código que solicite as informações de um usuário e as use para adquirir um token de acesso. O exemplo de banco de dados de pedidos de clientes encapsula chamadas do Microsoft Graph com a biblioteca WebAccountManager para adquirir um token e manipular a autenticação para uma conta do AAD.

Chamadas REST

Você não precisará modificar nenhum código que adicionamos neste tutorial para implementar chamadas REST. Em vez disso, será necessário fazer o seguinte:

  • Crie implementações das interfaces ICustomerRepository e ITutorialRepository, implementando o mesmo conjunto de funções por meio de REST em vez de SQLite. Você precisará serializar e desserializar JSON e poderá encapsular suas chamadas REST em uma classe HttpHelper se precisar. Consulte o exemplo completo para ver informações específicas.
  • Em App.xaml.cs, crie uma função para inicializar o repositório REST e chame-o em vez de SqliteDatabase quando o aplicativo for inicializado. Novamente, consulte o exemplo completo.

Depois que todas essas três etapas forem concluídas, você poderá se autenticar em sua conta do AAD por meio do aplicativo. As chamadas REST para o banco de dados remoto substituirão as chamadas SQLite locais, mas a experiência do usuário deverá ser a mesma. Se você ainda tiver disposições mais ambiciosas, poderá adicionar uma página de configurações para permitir que o usuário alterne dinamicamente entre os dois.