Share via


Criando exibições HTML usando modelos razor

No mundo do desenvolvimento móvel, o termo "aplicativo híbrido" normalmente se refere a um aplicativo que apresenta algumas (ou todas) de suas telas como páginas HTML dentro de um controle de visualizador da Web hospedado.

Há alguns ambientes de desenvolvimento que permitem criar seu aplicativo móvel inteiramente em HTML e JavaScript, no entanto, esses aplicativos podem sofrer problemas de desempenho ao tentar realizar efeitos complexos de processamento ou interface do usuário e também são limitados nos recursos da plataforma que podem acessar.

O Xamarin oferece o melhor dos dois mundos, especialmente ao utilizar o mecanismo de modelagem HTML razor. Com o Xamarin, você tem a flexibilidade de criar exibições HTML com modelo multiplataforma que usam JavaScript e CSS, mas também têm acesso completo às APIs da plataforma subjacente e ao processamento rápido usando C#.

Este documento explica como usar o mecanismo de modelagem razor para criar exibições HTML+JavaScript+CSS que podem ser usadas em plataformas móveis usando o Xamarin.

Usando exibições da Web programaticamente

Antes de sabermos sobre o Razor, esta seção aborda como usar exibições da Web para exibir conteúdo HTML diretamente – especificamente o conteúdo HTML gerado em um aplicativo.

O Xamarin fornece acesso completo às APIs de plataforma subjacentes no iOS e no Android, portanto, é fácil criar e exibir HTML usando C#. A sintaxe básica para cada plataforma é mostrada abaixo.

iOS

Exibir HTML em um controle UIWebView no Xamarin.iOS também usa apenas algumas linhas de código:

var webView = new UIWebView (View.Bounds);
View.AddSubview(webView);
string contentDirectoryPath = Path.Combine (NSBundle.MainBundle.BundlePath, "Content/");
var html = "<html><h1>Hello</h1><p>World</p></html>";
webView.LoadHtmlString(html, NSBundle.MainBundle.BundleUrl);

Confira as receitas do iOS UIWebView para obter mais detalhes sobre como usar o controle UIWebView.

Android

A exibição de HTML em um controle WebView usando o Xamarin.Android é realizada em apenas algumas linhas de código:

// webView is declared in an AXML layout file
var webView = FindViewById<WebView> (Resource.Id.webView);

// enable JavaScript execution in your html view so you can provide "alerts" and other js
webView.SetWebChromeClient(new WebChromeClient());

var html = "<html><h1>Hello</h1><p>World</p></html>";
webView.LoadDataWithBaseURL("file:///android_asset/", html, "text/html", "UTF-8", null);

Confira as receitas do Android WebView para obter mais detalhes sobre como usar o controle WebView.

Especificando o diretório base

Em ambas as plataformas, há um parâmetro que especifica o diretório base para a página HTML. Esse é o local no sistema de arquivos do dispositivo que é usado para resolve referências relativas a recursos como imagens e arquivos CSS. Por exemplo, marcas como

<link rel="stylesheet" href="style.css" />
<img src="monkey.jpg" />
<script type="text/javascript" src="jscript.js">

consulte estes arquivos: style.css, monkey.jpg e jscript.js. A configuração do diretório base informa à exibição da Web onde esses arquivos estão localizados para que possam ser carregados na página.

iOS

A saída do modelo é renderizada no iOS com o seguinte código C#:

webView.LoadHtmlString (page, NSBundle.MainBundle.BundleUrl);

O diretório base é especificado como NSBundle.MainBundle.BundleUrl o que se refere ao diretório no qual o aplicativo está instalado. Todos os arquivos na pasta Recursos são copiados para esse local, como o arquivo style.css mostrado aqui:

Solução iPhoneHybrid

A Ação de Build para todos os arquivos de conteúdo estático deve ser BundleResource:

Ação de build de projeto do iOS: BundleResource

Android

O Android também exige que um diretório base seja passado como um parâmetro quando cadeias de caracteres html são exibidas em um modo de exibição da Web.

webView.LoadDataWithBaseURL("file:///android_asset/", page, "text/html", "UTF-8", null);

A cadeia de caracteres especial file:///android_asset/ refere-se à pasta Ativos do Android em seu aplicativo, mostrada aqui contendo o arquivo style.css .

Solução AndroidHybrid

A Ação de Build para todos os arquivos de conteúdo estático deve ser AndroidAsset.

Ação de build de projeto do Android: AndroidAsset

Chamando C# de HTML e JavaScript

Quando uma página html é carregada em um modo de exibição da Web, ela trata os links e formulários como faria se a página fosse carregada de um servidor. Isso significa que, se o usuário clicar em um link ou enviar um formulário, o modo de exibição da Web tentará navegar até o destino especificado.

Se o link for para um servidor externo (como google.com), o modo de exibição da Web tentará carregar o site externo (supondo que haja uma conexão com a Internet).

<a href="http://google.com/">Google</a>

Se o link for relativo, o modo de exibição da Web tentará carregar esse conteúdo do diretório base. Obviamente, nenhuma conexão de rede é necessária para que isso funcione, pois o conteúdo é armazenado no aplicativo no dispositivo.

<a href="somepage.html">Local content</a>

As ações de formulário seguem a mesma regra.

<form method="get" action="http://google.com/"></form>
<form method="get" action="somepage.html"></form>

Você não vai hospedar um servidor Web no cliente; no entanto, você pode usar as mesmas técnicas de comunicação de servidor empregadas nos padrões de design responsivos de hoje para chamar serviços via HTTP GET e lidar com respostas de forma assíncrona, emitindo JavaScript (ou chamando JavaScript já hospedado no modo de exibição da Web). Isso permite que você passe facilmente dados do HTML de volta para o código C# para processamento e, em seguida, exiba os resultados de volta na página HTML.

Tanto o iOS quanto o Android fornecem um mecanismo para o código do aplicativo interceptar esses eventos de navegação para que o código do aplicativo possa responder (se necessário). Esse recurso é crucial para criar aplicativos híbridos porque permite que o código nativo interaja com o modo de exibição da Web.

iOS

O evento ShouldStartLoad no modo de exibição da Web no iOS pode ser substituído para permitir que o código do aplicativo manipule uma solicitação de navegação (como um clique de link). Os parâmetros de método fornecem todas as informações

bool HandleShouldStartLoad (UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType) {
    // return true if handled in code
    // return false to let the web view follow the link
}

e, em seguida, atribua o manipulador de eventos:

webView.ShouldStartLoad += HandleShouldStartLoad;

Android

No Android, basta subclasse WebViewClient e implemente o código para responder à solicitação de navegação.

class HybridWebViewClient : WebViewClient {
    public override bool ShouldOverrideUrlLoading (WebView webView, IWebResourceRequest request) {
        // return true if handled in code
        // return false to let the web view follow the link
    }
}

e, em seguida, defina o cliente no modo de exibição da Web:

webView.SetWebViewClient (new HybridWebViewClient ());

Chamando JavaScript de C#

Além de dizer a um modo de exibição da Web para carregar uma nova página HTML, o código C# também pode executar JavaScript na página exibida no momento. Blocos de código JavaScript inteiros podem ser criados usando cadeias de caracteres C# e executados, ou você pode criar chamadas de método para JavaScript já disponíveis na página por meio de script marcas.

Android

Crie o código JavaScript a ser executado e prefixe-o com "javascript:" e instrua o modo de exibição da Web a carregar essa cadeia de caracteres:

var js = "alert('test');";
webView.LoadUrl ("javascript:" + js);

iOS

As exibições da Web do iOS fornecem um método especificamente para chamar JavaScript:

var js = "alert('test');";
webView.EvaluateJavascript (js);

Resumo

Esta seção introduziu os recursos dos controles de exibição da Web no Android e no iOS que permitem criar aplicativos híbridos com o Xamarin, incluindo:

  • A capacidade de carregar HTML de cadeias de caracteres geradas no código,
  • A capacidade de referenciar arquivos locais (CSS, JavaScript, Imagens ou outros arquivos HTML),
  • A capacidade de interceptar solicitações de navegação no código C#,
  • A capacidade de chamar JavaScript do código C#.

A próxima seção apresenta o Razor, o que facilita a criação do HTML a ser usado em aplicativos híbridos.

O que é o Razor?

O Razor é um mecanismo de modelagem que foi introduzido com ASP.NET MVC, originalmente para ser executado no servidor e gerar HTML a ser servido aos navegadores da Web.

O mecanismo de modelagem razor estende a sintaxe HTML padrão com C# para que você possa expressar o layout e incorporar folhas de estilos CSS e JavaScript facilmente. O modelo pode referenciar uma classe Model, que pode ser qualquer tipo personalizado e cujas propriedades podem ser acessadas diretamente do modelo. Uma de suas vantagens main é a capacidade de misturar a sintaxe HTML e C# facilmente.

Os modelos razor não se limitam ao uso do lado do servidor, eles também podem ser incluídos em aplicativos Xamarin. O uso de modelos razor, juntamente com a capacidade de trabalhar com exibições da Web programaticamente, permite que aplicativos híbridos sofisticados multiplataforma sejam criados com o Xamarin.

Noções básicas do modelo razor

Os arquivos de modelo razor têm uma extensão de arquivo .cshtml . Eles podem ser adicionados a um projeto Xamarin na seção Modelagem de Texto na caixa de diálogo Novo Arquivo :

Novo Arquivo – Modelo razor

Um modelo razor simples ( RazorView.cshtml) é mostrado abaixo.

@model string
<html>
    <body>
    <h1>@Model</h1>
    </body>
</html>

Observe as seguintes diferenças de um arquivo HTML regular:

  • O @ símbolo tem um significado especial em modelos razor – indica que a expressão a seguir é C# a ser avaliada.
  • @model A diretiva sempre aparece como a primeira linha de um arquivo de modelo razor.
  • A @model diretiva deve ser seguida por um Tipo. Neste exemplo, uma cadeia de caracteres simples está sendo passada para o modelo, mas pode ser qualquer classe personalizada.
  • Quando @Model é referenciado em todo o modelo, ele fornece uma referência ao objeto passado para o modelo quando ele é gerado (neste exemplo, será uma cadeia de caracteres).
  • O IDE gerará automaticamente a classe parcial para modelos (arquivos com a extensão .cshtml ). Você pode exibir esse código, mas ele não deve ser editado. RazorView.cshtml A classe parcial é denominada RazorView para corresponder ao nome do arquivo de modelo .cshtml. É esse nome que é usado para se referir ao modelo no código C#.
  • @using as instruções também podem ser incluídas na parte superior de um modelo razor para incluir namespaces adicionais.

A saída HTML final pode ser gerada com o código C# a seguir. Observe que especificamos o Modelo para ser uma cadeia de caracteres "Olá, Mundo" que será incorporada à saída do modelo renderizado.

var template = new RazorView () { Model = "Hello World" };
var page = template.GenerateString ();

Aqui está a saída mostrada em um modo de exibição da Web no Simulador do iOS e no Android Emulator:

Olá, Mundo

Mais sintaxe razor

Nesta seção, apresentaremos uma sintaxe básica do Razor para ajudá-lo a começar a usá-la. Os exemplos nesta seção preenchem a seguinte classe com dados e os exibem usando o Razor:

public class Monkey {
    public string Name { get; set; }
    public DateTime Birthday { get; set; }
    public List<string> FavoriteFoods { get; set; }
}

Todos os exemplos usam o código de inicialização de dados a seguir

var animal = new Monkey {
    Name = "Rupert",
    Birthday=new DateTime(2011, 04, 01),
    FavoriteFoods = new List<string>
        {"Bananas", "Banana Split", "Banana Smoothie"}
};

Exibindo propriedades do modelo

Quando o modelo é uma classe com propriedades, eles são facilmente referenciados no modelo razor, conforme mostrado neste modelo de exemplo:

@model Monkey
<html>
    <body>
    <h1>@Model.Name</h1>
    <p>Birthday: @(Model.Birthday.ToString("d MMMM yyyy"))</p>
    </body>
</html>

Isso pode ser renderizado em uma cadeia de caracteres usando o seguinte código:

var template = new RazorView () { Model = animal };
var page = template.GenerateString ();

A saída final é mostrada aqui em um modo de exibição da Web no Simulador do iOS e no Android Emulator:

Rupert

Instruções C#

C# mais complexo pode ser incluído no modelo, como as atualizações de propriedade Model e o cálculo idade neste exemplo:

@model Monkey
<html>
    <body>
    @{
        Model.Name = "Rupert X. Monkey";
        Model.Birthday = new DateTime(2011,3,1);
    }
    <h1>@Model.Name</h1>
    <p>Birthday: @Model.Birthday.ToString("d MMMM yyyy")</p>
    <p>Age: @(Math.Floor(DateTime.Now.Date.Subtract (Model.Birthday.Date).TotalDays/365)) years old</p>
    </body>
</html>

Você pode escrever expressões complexas de C# de linha única (como formatar a idade) ao redor do código com @().

Várias instruções C# podem ser escritas cercando-as com @{}.

Instruções If-else

Os branches de código podem ser expressos com @if , conforme mostrado neste exemplo de modelo.

@model Monkey
<html>
    <body>
    <h1>@Model.Name</h1>
    <p>Birthday: @(Model.Birthday.ToString("d MMMM yyyy"))</p>
    <p>Age: @(Math.Floor(DateTime.Now.Date.Subtract (Model.Birthday.Date).TotalDays/365)) years old</p>
    <p>Favorite Foods:</p>
    @if (Model.FavoriteFoods.Count == 0) {
        <p>No favorites</p>
    } else {
        <p>@Model.FavoriteFoods.Count favorites</p>
    }
    </body>
</html>

Loops

Constructos de loop como foreach também podem ser adicionados. O @ prefixo pode ser usado na variável de loop ( @food nesse caso) para renderizá-lo em HTML.

@model Monkey
<html>
    <body>
    <h1>@Model.Name</h1>
    <p>Birthday: @Model.Birthday.ToString("d MMMM yyyy")</p>
    <p>Age: @(Math.Floor(DateTime.Now.Date.Subtract (Model.Birthday.Date).TotalDays/365)) years old</p>
    <p>Favorite Foods:</p>
    @if (Model.FavoriteFoods.Count == 0) {
        <p>No favorites</p>
    } else {
        <ul>
            @foreach (var food in @Model.FavoriteFoods) {
                <li>@food</li>
            }
        </ul>
    }
    </body>
</html>

A saída do modelo acima é mostrada em execução no Simulador do iOS e no Android Emulator:

Rupert X Monkey

Esta seção abordou os conceitos básicos do uso de modelos do Razor para renderizar exibições simples somente leitura. A próxima seção explica como criar aplicativos mais completos usando o Razor que podem aceitar entrada do usuário e interoperar entre JavaScript na exibição HTML e C#.

Usando modelos do Razor com o Xamarin

Esta seção explica como usar o build de seu próprio aplicativo híbrido usando os modelos de solução no Visual Studio para Mac. Há três modelos disponíveis na janela Arquivo > Nova > Solução... :

  • > Aplicativo Android > Android WebView Application
  • Aplicativo iOS >> WebView
  • Projeto ASP.NET MVC

A janela Nova Solução tem esta aparência para projetos iPhone e Android – a descrição da solução à direita realça o suporte para o mecanismo de modelagem razor.

Criando soluções para iPhone e Android

Observe que você pode adicionar facilmente um modelo razor .cshtml a qualquer projeto Xamarin existente, não é necessário usar esses modelos de solução. Os projetos do iOS também não exigem um Storyboard para usar o Razor; basta adicionar um controle UIWebView a qualquer exibição programaticamente e você pode renderizar modelos Razor inteiros no código C#.

O conteúdo da solução de modelo padrão para projetos iPhone e Android é mostrado abaixo:

Modelos de iPhone e Android

Os modelos oferecem uma infraestrutura de aplicativo pronta para uso para carregar um modelo do Razor com um objeto de modelo de dados, processar a entrada do usuário e se comunicar com o usuário por meio do JavaScript.

As partes importantes da solução são:

  • Conteúdo estático, como o arquivo style.css .
  • Arquivos de modelo .cshtml razor como RazorView.cshtml .
  • Classes de modelo que são referenciadas nos modelos do Razor, como ExampleModel.cs .
  • A classe específica da plataforma que cria o modo de exibição da Web e renderiza o modelo, como no MainActivity Android e no iPhoneHybridViewController iOS.

A seção a seguir explica como os projetos funcionam.

Conteúdo Estático

O conteúdo estático inclui folhas de estilos CSS, imagens, arquivos JavaScript ou outro conteúdo que pode ser vinculado ou referenciado por um arquivo HTML que está sendo exibido em um modo de exibição da Web.

Os projetos de modelo incluem uma folha de estilos mínima para demonstrar como incluir conteúdo estático em seu aplicativo híbrido. A folha de estilos do CSS é referenciada no modelo desta forma:

<link rel="stylesheet" href="style.css" />

Você pode adicionar qualquer folha de estilos e arquivos JavaScript necessários, incluindo estruturas como JQuery.

Modelos de cshtml do Razor

O modelo inclui um arquivo .cshtml razor que tem código pré-escrito para ajudar a comunicar dados entre HTML/JavaScript e C#. Isso permitirá que você crie aplicativos híbridos sofisticados que não apenas exibam dados somente leitura do Modelo, mas também aceitem a entrada do usuário no HTML e os passem de volta para o código C# para processamento ou armazenamento.

Como renderizar o modelo

Chamar o GenerateString em um modelo renderiza HTML pronto para exibição em um modo de exibição da Web. Se o modelo usar um modelo, ele deverá ser fornecido antes da renderização. Este diagrama ilustra como a renderização funciona – não que os recursos estáticos sejam resolvidos pelo modo de exibição da Web em runtime, usando o diretório base fornecido para localizar os arquivos especificados.

Fluxograma razor

Chamando o código C# do modelo

A comunicação de um modo de exibição da Web renderizado chamando de volta para C# é feita definindo a URL para o modo de exibição da Web e interceptando a solicitação em C# para lidar com a solicitação nativa sem recarregar o modo de exibição da Web.

Um exemplo pode ser visto em como o botão do RazorView é tratado. O botão tem o seguinte HTML:

<input type="button" name="UpdateLabel" value="Click" onclick="InvokeCSharpWithFormValues(this)" />

A InvokeCSharpWithFormValues função JavaScript lê todos os valores do Formulário HTML e define o location.href para o modo de exibição da Web:

location.href = "hybrid:" + elm.name + "?" + qs;

Isso tenta navegar no modo de exibição da Web para uma URL com um esquema personalizado (por exemplo, hybrid:)

hybrid:UpdateLabel?textbox=SomeValue&UpdateLabel=Click

Quando a exibição da Web nativa processa essa solicitação de navegação, temos a oportunidade de interceptá-la. No iOS, isso é feito manipulando o evento HandleShouldStartLoad da UIWebView. No Android, simplesmente subclasse o WebViewClient usado no formulário e substituimos ShouldOverrideUrlLoading.

Os internos desses dois interceptadores de navegação são essencialmente os mesmos.

Primeiro, marcar a URL que o modo de exibição da Web está tentando carregar e, se não começar com o esquema personalizado (hybrid:), permita que a navegação ocorra normalmente.

Para o esquema de URL personalizado, tudo na URL entre o esquema e o "?" é o nome do método a ser tratado (nesse caso, "UpdateLabel"). Tudo na cadeia de caracteres de consulta será tratado como os parâmetros para a chamada de método:

var resources = url.Substring(scheme.Length).Split('?');
var method = resources [0];
var parameters = System.Web.HttpUtility.ParseQueryString(resources[1]);

UpdateLabel neste exemplo faz uma quantidade mínima de manipulação de cadeia de caracteres no parâmetro textbox (anexando "C# says" à cadeia de caracteres) e, em seguida, chama de volta para o modo de exibição da Web.

Depois de manipular a URL, o método anula a navegação para que o modo de exibição da Web não tente concluir a navegação até a URL personalizada.

Manipulando o modelo de C#

A comunicação com uma exibição da Web HTML renderizada do C# é feita chamando JavaScript no modo de exibição da Web. No iOS, isso é feito chamando EvaluateJavascript no UIWebView:

webView.EvaluateJavascript (js);

No Android, o JavaScript pode ser invocado no modo de exibição da Web carregando o JavaScript como uma URL usando o "javascript:" esquema de URL:

webView.LoadUrl ("javascript:" + js);

Tornando um aplicativo verdadeiramente híbrido

Esses modelos não usam controles nativos em cada plataforma – a tela inteira é preenchida com uma única exibição da Web.

HTML pode ser ótimo para criação de protótipos e exibir os tipos de coisas em que a Web é melhor, como rich text e layout responsivo. No entanto, nem todas as tarefas são adequadas para HTML e JavaScript – rolar por longas listas de dados, por exemplo, funciona melhor usando controles de interface do usuário nativos (como UITableView no iOS ou ListView no Android).

As exibições da Web no modelo podem ser facilmente aumentadas com controles específicos da plataforma – basta editar o MainStoryboard.storyboard usando o Xcode em um Mac ou o Resources/layout/Main.axml no Android.

Exemplo de RazorTodo

O repositório RazorTodo contém duas soluções separadas para mostrar as diferenças entre um aplicativo completamente controlado por HTML e um aplicativo que combina HTML com controles nativos:

  • RazorTodo – aplicativo totalmente controlado por HTML usando modelos do Razor.
  • RazorNativeTodo – usa controles de exibição de lista nativos para iOS e Android, mas exibe a tela de edição com HTML e Razor.

Esses aplicativos Xamarin são executados no iOS e no Android, utilizando PCLs (Bibliotecas de Classes Portáteis) para compartilhar código comum, como o banco de dados e as classes de modelo. Os modelos .cshtml do Razor também podem ser incluídos na PCL para que sejam facilmente compartilhados entre plataformas.

Ambos os aplicativos de exemplo incorporam o compartilhamento do Twitter e as APIs de conversão de texto em fala da plataforma nativa, demonstrando que aplicativos híbridos com Xamarin ainda têm acesso a todas as funcionalidades subjacentes de exibições orientadas por modelo do Razor HTML.

O aplicativo RazorTodo usa modelos razor HTML para a lista e editar exibições. Isso significa que podemos criar o aplicativo quase completamente em uma Biblioteca de Classes Portátil compartilhada (incluindo o banco de dados e modelos razor .cshtml ). As capturas de tela abaixo mostram os aplicativos iOS e Android.

RazorTodo

O aplicativo RazorNativeTodo usa um modelo Razor HTML para o modo de exibição de edição, mas implementa uma lista de rolagem nativa em cada plataforma. Isso oferece uma série de benefícios, incluindo:

  • Desempenho – os controles de rolagem nativos usam virtualização para garantir uma rolagem rápida e suave, mesmo com listas de dados muito longas.
  • Experiência nativa – elementos de interface do usuário específicos da plataforma são facilmente habilitados, como o suporte ao índice de rolagem rápida no iOS e no Android.

Um dos principais benefícios da criação de aplicativos híbridos com o Xamarin é que você pode começar com uma interface do usuário completamente controlada por HTML (como o primeiro exemplo) e, em seguida, adicionar funcionalidade específica da plataforma quando necessário (como mostra o segundo exemplo). As telas de lista nativa e as telas de edição do Razor HTML no iOS e no Android são mostradas abaixo.

RazorNativeTodo

Resumo

Este artigo explicou os recursos dos controles de exibição da Web disponíveis no iOS e no Android que facilitam a criação de aplicativos híbridos.

Em seguida, ele discutiu o mecanismo de modelagem razor e a sintaxe que pode ser usada para gerar HTML facilmente em aplicativos Xamarin usando . Cshtml Arquivos de modelo do Razor. Ele também descreveu os modelos de solução Visual Studio para Mac que permitem que você comece rapidamente a criar aplicativos híbridos com o Xamarin.

Por fim, ele introduziu os exemplos do RazorTodo que demonstram como combinar exibições da Web com interfaces de usuário nativas e APIs.