Blazor - Calculando a área da superfície de um cilindro

Hoje vamos usar o Blazor para calcular a área da superfície de um cilindro em uma aplicação SPA do lado do cliente sem usar JavaScript mas apenas C#.

Se você esta chegando agora e não sabe o que é o Blazor leia o artigo ASP .NET Core - Iniciando com o Blazor - Macoratti; se você já conhece e quer saber mais pode fazer o curso de Blazor Essencial.  

Hoje teremos uma aplicação que calcula a área da superfície de um cilindro. Nesta aplicação veremos alguns recursos básicos do Blazor como uso de componentes e o cálculo da área feita usando a linguagem C#.

Tudo isso rodando do lado do cliente em uma aplicação Single Page Application.

Recursos usados:

Criando o projeto Blazor (Cliente side) no VS Community 2019

Abra o VS 2019 Community (versão mínima 16.3) 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_Areas, 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 segunda opção - Blazor WebAssembly App - e deixe desmarcada a opção - ASP.NET Core hosted:

Assim vamos criar um projeto WebAssembly que roda do lado do cliente com a estrutura abaixo:

A pasta wwwroot é onde os recursos estáticos usados pela aplicação são colocados.

No arquivo Index.cshtml temos a inicialização da aplicação e a carga do WebAssembly.

As pastas Pages e Shared são as mais importantes do projeto e contém componentes que são arquivos com a extensão .razor.

Na pasta Pages temos os componentes roteados, ou seja, que possuem uma rota definida usando a diretiva @page.

Na pasta Shared temos os componentes não roteados e que podem ser compartilhados com os demais componentes.

O arquivo _Imports.razor é onde definimos os namespaces que poderão ser compartilhados com todos os componentes.

O arquivo App.razor é esta definindo o roteamento e o layout padrão usado no projeto.

No arquivo Startup.cs podemos configurar serviços e recursos da mesma forma que fazemos na ASP .NET Core.

Ajustando o projeto criado

Será criado um projeto padrão que vamos ajustar da seguinte forma:

  • Na pasta Pages vamos remover os arquivos FetchData.razor;
  • Na pasta Pages vamos alterar o nome do arquivo Counter.razor para Area.razor;
  • Na pasta Shared vamos remover o arquivo SurveyPrompt.razor;

Na pasta wwwroot vamos criar a pasta images e nesta pasta vamos incluir a imagem que iremos usar em nosso projeto : cilindro.jpg

O arquivo NavMenu é onde definimos os links para o menu da aplicação. Vamos alterar o conteúdo deste arquivo conforme abaixo:

<div class="top-row pl-4 navbar navbar-dark">
    <a class="navbar-brand" href="">Blazor_Areas</a>
    <button class="navbar-toggler" @onclick="ToggleNavMenu">
        <span class="navbar-toggler-icon"></span>
    </button>
</div>
<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-calculator" aria-hidden="true"></span> Cilindro
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="area">
                <span class="oi oi-book" aria-hidden="true"></span> Área
            </NavLink>
        </li>
    </ul>
</div>
@code {
    bool collapseNavMenu = true;
    string NavMenuCssClass => collapseNavMenu ? "collapse" : null;
    void ToggleNavMenu()
    {
        collapseNavMenu = !collapseNavMenu;
    }

Alteramos os links do menu para exibir os links com os textos: Calcula Idade e Sobre

Alterando o código do componente Area.razor

O arquivo Sobre.razor é um componente onde usando a diretiva @page definimos a rota '/area' para acessar este componente. Também estamos exibindo a imagem cilindro.jpg.

Aqui temos somente código HTML:

@page "/area"
<img src="/images/cilindro.jpg" />

Criando o componente Aviso.razor

Vamos criar um componente chamado Aviso na pasta Shared que será um componente não roteado que vamos usar para exibir um aviso genérico no projeto.

Crie o arquivo Aviso.razor na pasta Shared e inclua o código abaixo:

@if (Exibir)
{
    <div class="alert alert-secondary mt-4" role="alertdialog">
        @ChildContent
    </div>
}
@code {
    [Parameter]
    public bool Exibir { get; set; }
    [Parameter]
    public RenderFragment ChildContent { get; set; }
}

Neste componente usamos alguns recursos do Blazor como Parameter, ChildContent e RenderFragment.

Os componentes podem ter parâmetros de componente, que são definidos usando propriedades públicas na classe de componente com o atributo [Parameter]. Usamos atributos para especificar argumentos para um componente no código de marcação HTML.

No código acima, o componente Aviso tem uma propriedade ChildContent que representa um RenderFragment, que representa um segmento de interface do usuário a ser renderizado. O valor de ChildContent é posicionado na marcação do componente onde o conteúdo deve ser renderizado. O valor de ChildContent é recebido do componente pai e renderizado dentro do panel-body do painel de inicialização.

Assim RenderFragment pode renderizar qualquer conteúdo como código de marcação.

Agora que temos o nosso componente pronto podemos usá-lo no componente Index.

Para isso definimos a tag :

<Aviso Exibir="Exibir">
    <h5>@Mensagem</h5>
</Aviso>

- Exibir é uma variável do tipo booleana que indica se vamos exibir ou não o aviso;
- Mensagem é um parâmetro onde vamos definir o texto da mensagem que vamos exibir;

Assim teremos que definir no componente Index a variável booleand Exibir e o parâmetro Mensagem.

Alterando o código do componente Index.razor

O componente Index.razor é o componente principal do nosso projeto e onde vamos definir o cálculo da área.

Neste arquivo temos a diretiva @code onde definimos código C# para fazer o cálculo da área da superfície do cilindro:

@page "/"
<h3>Cálculo da área da superfício de um Cilíndro</h3>
<hr />
<img src="/images/cilindro.jpg" />
<h3> A = 2π r h + 2π r<sup>2</sup>   ou   A = 2π r(h + r) </h3>
<hr />
<p>
    <input class="inputstyle" @bind="@A" placeholder="A" /> =
    2π * <input @bind="@r" class="inputstyle" placeholder="r" /> ∗
    <input @bind="@h" class="inputstyle" placeholder="h" />
    + 2π * <input @bind="@r" class="inputstyle" placeholder="r" /><sup>2</sup>
</p>
<hr />
<button @onclick="LimparTudo">Limpar</button>
<hr />
<p>A = área <button @onclick="@Calcular_A" disabled="@IsDisabledA" >Calcular A</button></p>
<p>r = raio <button @onclick="@Calcular_r" disabled="@IsDisabledr">calcular r</button></p>
<p> π = @Math.PI</p>
<p> h = altura <button @onclick="@Calcular_h" disabled="@IsDisabledh">calcular h</button></p>
<hr />

<Aviso Exibir="exibir">
    <h3>@mensagem</h3>
</Aviso>
@code {
    double r = 0;
    double h = 0;
    double A = 0;
    bool exibir = false;
    public bool IsDisabledA { get; set; } = false;
    public bool IsDisabledh { get; set; } = false;
    public bool IsDisabledr { get; set; } = false;
    [Parameter]
    public string mensagem { get; set; }
    void LimparTudo()
    {
        r = 0;
        h = 0;
        A = 0;
        exibir = false;
        IsDisabledh = false;
        IsDisabledr = false;
        IsDisabledA = false;
    }
    void Calcular_A()
    {
        if (r != 0 || h != 0)
        {
            exibir = false;
            IsDisabledh = true;
            IsDisabledr = true;
            A = 2 * Math.PI * r * h + 2 * Math.PI * (Math.Pow(h, 2));
        }
        else
        {
            exibir = true;
            mensagem = $"Informe o valor do raio(r) e da altura(h)";
        }
    }
    void Calcular_r()
    {
        if (A != 0 || h != 0)
        {
            exibir = false;
            r = 0.5 * Math.Sqrt(Math.Pow(h, 2) + 2 * (A / Math.PI)) - (h / 2);
        }
        else
        {
            exibir = true;
            IsDisabledA = true;
            IsDisabledh = true;
            mensagem = $"Informe o valor da área(A) e da altura(h)";
        }
    }
    void Calcular_h()
    {
        if (r != 0 || A != 0)
        {
            exibir = false;
            h = (A / (2 * Math.PI * r)) - r;
        }
        else
        {
            IsDisabledA = true;
            IsDisabledr = true;
            exibir = true;
            mensagem = $"Informe o valor do raio(r) e da área(A)";
        }
    }
}

Vamos entender o código :

1- Definimos um tag input onde estamos fazendo o databinding usando o atributo @bind com as varáveis que representam a altura, a área e o raio do cilindro bem com a fórmula do cálculo de sua área.

<p>
    <input class="inputstyle" @bind="@A" placeholder="A" /> =
    2π * <input @bind="@r" class="inputstyle" placeholder="r" /> ∗
    <input @bind="@h" class="inputstyle" placeholder="h" />
    + 2π * <input @bind="@r" class="inputstyle" placeholder="r" /><sup>2</sup>
</p>

2- A seguir temos os buttons onde definimos o evento @onclick que acessa os métodos referenciados:

<button @onclick="LimparTudo">Limpar</button>
<hr />
<p>A = área <button @onclick="@Calcular_A" disabled="@IsDisabledA" >Calcular A</button></p>
<p>r = raio <button @onclick="@Calcular_r" disabled="@IsDisabledr">calcular r</button></p>
<p> π = @Math.PI</p>
<p> h = altura <button @onclick="@Calcular_h" disabled="@IsDisabledh">calcular h</button></p>
<hr />

3- Depois estamos usando o componente Aviso que criamos anteriormente:

<Aviso Exibir="exibir">
    <h3>@mensagem</h3>
</Aviso>

Agora temos a definição do código C# na diretiva @code:

1 - Definimos as variáveis usadas no código e o parametro mensagem:

    double r = 0;
    double h = 0;
    double A = 0;
    bool exibir = false;
    public bool IsDisabledA { get; set; } = false;
    public bool IsDisabledh { get; set; } = false;
    public bool IsDisabledr { get; set; } = false;
    [Parameter]
    public string mensagem { get; set; }

2 - A seguir temos os métodos para calcular a área, o raio e a altura.

Cabe destacar neste código que estamos usando o DataBinding em atributos que não propriamente recebem valor, e sim modificam o comportamento de um elemento HTML apenas pela sua presença na Tag.

Aqui estamos usando o atributo disabled para desabilitar alguns buttons em nossa página.(Poderíamos fazer isso também para a tag input).

O Blazor permite que façamos Bind em atributos condicionais, como é o caso do disabled, e, é isso que estamos fazendo aqui.

Executando o projeto iremos obter o resultado abaixo:

Pegue o código do projeto aqui:   Blazor_Areas.zip (sem as referências)
 


Referências:


José Carlos Macoratti