Blazor -  Exibindo Mestre-Detalhes com RadzenGrid


Hoje veremos como usar o componente RadzenGrid da biblioteca Radzen.Blazor para realizar a exibição mestre-detalhes.

A biblioteca Blazor Radzen, que pode ser instalada como um pacote Nuget,  apresenta dezenas de componenets gratuitos que podem ser usados em aplicações Blazor do lado do cliente (WASM) e do lado do servidor.

Os componentes Radzen Blazor são distribuídos como um pacote nuget Radzen.Blazor (atualmente na versão 2.1.9) :  https://www.nuget.org/packages/Radzen.Blazor/

Você pode obter mais detalhes com exemplos de utilização dos componentes no site oficial neste link: https://blazor.radzen.com

Hoje vamos usar o componente RadzenGrid e mostrar como realizar uma exibição mestre-detalhes.

Recursos usados:

Criando o projeto Blazor Server no VS Community 2019

bra o VS 2019 Community (versão mínima 16.4) e selecione a opção Create a New Project;

A seguir selecione a opção Blazor app e clique em next;

Informe o nome do projeto :  Blazor_AppMasterDetail, a localização e clique em Create;

A seguir teremos uma janela com duas opções :

  1. Blazor Server App
  2. Blazor WebAssembly App

Selecione a primeira opção - Blazor Server App. Não vamos usar autenticação e vamos habilitar o https.

Clique no botão Create para criar o projeto.

Antes de prosseguir vamos limpar o projeto excluindo os arquivos abaixo e suas referências:

Vamos também ajustar o arquivo NavMenu.razor deixando apenas a opção Home e a opção Pedidos para acessar o componente Pedidos.razor que iremos criar para exibir o grid.

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="" Match="NavLinkMatch.All">
                <span class="oi oi-home" aria-hidden="true"></span> Home
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="pedidos">
                <span class="oi oi-person" aria-hidden="true"></span> Pedidos
            </NavLink>
        </li>
    </ul>
</div>

Agora com o projeto criado e os ajustes feitos vamos incluir a referência ao pacote nuget que vamos usar.

Configurando o projeto : Referenciando o pacote MatBlazor

Clique no menu Tools > NuGet Package Manager > Manage NuGet Package For Solution.

E na guia Browse procure pelo pacote MatBlazor e instale o pacote no seu projeto:

NotaVocê também pode instalar usando a janela do Gerenciador de pacotes com o comando:
Install-Package Razen.Blazor -Version 2.3.3

Com o projeto criado vamos criar uma pasta images dentro da pasta wwwroot e incluir algumas imagens que iremos usar no projeto:

Abra o arquivo _Imports.razor  do projeto e inclua as referência aos namespaces @using Radzen e @using Blazor_AppMasterDetail.Data;

Essas referências serão usadas em nosso projeto pelos componentes que iremos criar.

@using System.Net.Http
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using Microsoft.JSInterop
@using Blazor_AppMasterDetail
@using Blazor_AppMasterDetail.Shared
@using Radzen
@using Blazor_AppMasterDetail.Data

Agora abra o arquivo _Host.cshtml da pasta Pages inclua uma referência ao arquivo Javascript Radzen.Blazor.js e ao arquivo de estilo default.css na seção header do arquivo:

@page "/"
@namespace Blazor_AppMasterDetail.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@{
    Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Blazor_AppMasterDetail</title>
    <base href="~/" />
    <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
    <link href="css/site.css" rel="stylesheet" />

    <link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css" />
    <script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>

</head>
<body>
    <app>
        <component type="typeof(App)" render-mode="ServerPrerendered" />
    </app>
    <div id="blazor-error-ui">
        <environment include="Staging,Production">
            An error has occurred. This application may no longer respond until reloaded.
        </environment>
        <environment include="Development">
            An unhandled exception has occurred. See browser dev tools for details.
        </environment>
        <a href="" class="reload">Reload</a>
        <a class="dismiss">🗙</a>
    </div>
    <script src="_framework/blazor.server.js"></script>
</body>
</html>

Criando um serviço para acessar os dados

Vamos aproveitar a pasta Data já criada no projeto e nesta pasta criar as classe Pedido e PedidoDetalhes que vão representar os nossos pedidos e seus detalhes e que são o nosso domínio:

Crie o arquivo Pedido.cs e inclua o código abaixo:

    public class Pedido
    {
        public int PedidoID { get; set; }
        public string ClienteNome { get; set; }
        public DateTime PedidoData { get; set; }
        public List<PedidoDetalhes> PedidoDetalhes { get; set; }
    }

A seguir crie a classe PedidoDetalhes com o código a seguir:

    public class PedidoDetalhes
    {
        public int PedidoID { get; set; }
        public int ProdutoID { get; set; }
        public string ProdutoNome { get; set; }
        public double? Quantidade { get; set; }
        public double? Preco { get; set; }
    }

Agora vamos criar a classe PedidoService onde vamos definir os dados das entidades Pedido e PedidoDetalhes e o método para retornar uma lista de Pedido e seus detalhes.

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

namespace Blazor_AppMasterDetail.Data
{
    public class PedidoService
    {
        List<Pedido>
pedidos = new List<Pedido>()
        {
            new Pedido() { PedidoID=1, ClienteNome="Marcos", PedidoData = Convert.ToDateTime("01-Mar-2019")},
            new Pedido() { PedidoID=2, ClienteNome="Pedro", PedidoData = Convert.ToDateTime("11-Mar-2019")},
            new Pedido() { PedidoID=3, ClienteNome="Maria", PedidoData = Convert.ToDateTime("08-Mar-2019")},
            new Pedido() { PedidoID=4, ClienteNome="Anita", PedidoData = Convert.ToDateTime("09-Mar-2019")},
            new Pedido() { PedidoID=5, ClienteNome="Carolina", PedidoData = Convert.ToDateTime("13-Mar-2019")}
        };

        List<PedidoDetalhes> pedidoDetalhes = new List<PedidoDetalhes>()
        {
            new PedidoDetalhes() {PedidoID = 1, ProdutoID = 10, ProdutoNome = "Caneta", Quantidade = 5, Preco = 12.45},
            new PedidoDetalhes() {PedidoID = 1, ProdutoID = 11, ProdutoNome = "Borracha", Quantidade = 3, Preco = 10.45},
            new PedidoDetalhes() {PedidoID = 2, ProdutoID = 12, ProdutoNome = "Lápis", Quantidade = 4, Preco = 11.25},
            new PedidoDetalhes() {PedidoID = 2, ProdutoID = 13, ProdutoNome = "Caderno", Quantidade = 3, Preco = 17.35},
            new PedidoDetalhes() {PedidoID = 3, ProdutoID = 14, ProdutoNome = "Estojo", Quantidade = 2, Preco = 9.40},
            new PedidoDetalhes() {PedidoID = 3, ProdutoID = 15, ProdutoNome = "Durex", Quantidade = 7, Preco = 15.30},
            new PedidoDetalhes() {PedidoID = 3, ProdutoID = 16, ProdutoNome = "Mouse", Quantidade = 1, Preco = 10.25},
            new PedidoDetalhes() {PedidoID = 4, ProdutoID = 11, ProdutoNome = "Borracha", Quantidade = 4, Preco = 10.99},
            new PedidoDetalhes() {PedidoID = 4, ProdutoID = 18, ProdutoNome = "Grampos", Quantidade = 30, Preco = 11.99},
            new PedidoDetalhes() {PedidoID = 5, ProdutoID = 19, ProdutoNome = "Clips", Quantidade = 10, Preco = 6.55},
            new PedidoDetalhes() {PedidoID = 5, ProdutoID = 10, ProdutoNome = "Caneta", Quantidade = 2, Preco = 8.22},
            new PedidoDetalhes() {PedidoID = 5, ProdutoID = 13, ProdutoNome = "Caderno", Quantidade = 1, Preco = 7.11}
        };

        public async Task<List<Pedido>> PedidoLista()
        {
            var novoPedidoLista = new List<Pedido>();
            foreach(var pedido in pedidos)
            {
                pedido.PedidoDetalhes = pedidoDetalhes.Where(p => p.PedidoID == pedido.PedidoID).ToList();
                novoPedidoLista.Add(pedido);
            }
            return await Task.FromResult(novoPedidoLista);
        }
    }
}

Agora temos que registrar o serviço criado no método ConfigureServices da classe Startup :

       public void ConfigureServices(IServiceCollection services)
        {
            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddScoped<PedidoService>();
        }

NotaSugiro que você leia este artigo: Hutch Codes — Dependency Injection Lifetimes in Blazor

Criando o componente Pedidos para exibir o mestre/detalhes

Vamos criar o componente Pedidos.razor na pasta Pages do projeto para poder exibir a lista de pedido e seus detalhes.

Crie o arquivo Pedidos.razor na pasta Pages com o código abaixo:

@page "/pedidos"
@inject PedidoService  pedidoService
@using Radzen.Blazor

@if (pedidos == null)
{
    <div>
        <img src="/images/basicloader.gif" />
    </div>
}
else
{
   <RadzenGrid Data="@pedidos" TItem="Pedido" AllowFiltering="true" AllowPaging="true" PageSize="5"
                             RowSelect="@(args=> pedido=args)">
       <Columns>
           <RadzenGridColumn TItem="Pedido" Property="PedidoID" Title="ID" />
           <RadzenGridColumn TItem="Pedido" Property="ClienteNome" Title="Cliente" />
           <RadzenGridColumn TItem="Pedido" Property="PedidoData" Title="Data" />
       </Columns>

   </RadzenGrid>
   <RadzenTabs>
       <Tabs>
           <RadzenTabsItem Text="Detalhes">
               <RadzenGrid AllowFiltering="true" AllowPaging="true" Data="@pedido.PedidoDetalhes" TItem="PedidoDetalhes">
                   <Columns>
                       <RadzenGridColumn TItem="PedidoDetalhes" Property="ProdutoID" Title="ID" />
                       <RadzenGridColumn TItem="PedidoDetalhes" Property="ProdutoNome" Title="Produto" />
                       <RadzenGridColumn TItem="PedidoDetalhes" Property="Quantidade" Title="Qtde" />
                       <RadzenGridColumn TItem="PedidoDetalhes" Property="Preco" Title="Preço" />
                   </Columns>

               </RadzenGrid>
           </RadzenTabsItem>
       </Tabs>
   </RadzenTabs>

}

@code {
    Pedido pedido = new Pedido();
    IEnumerable<Pedido> pedidos;

    protected override async Task OnInitializedAsync()
    {
        pedidos = await Task.Run(() => pedidoService.PedidoLista());
    }
}

Aqui usamos o componente RadzenGrid definindo algumas configurações básicas e criando as colunas para exibir os itens e os detalhes.

Os dados são obtidos no método OnInitializedAsync onde usamos a instância do serviço que foi injetado no arquivo.

Agora é só alegria...

Executando o projeto teremos o resultado abaixo:

Pegue o projeto aqui:   Blazor_AppMasterDetail.zip (sem as referências)

"Portanto, agora nenhuma condenação há para os que estão em Cristo Jesus, que não andam segundo a carne, mas segundo o Espírito."
Romanos 8:1

Referências:


José Carlos Macoratti