Compilazione di visualizzazioni HTML con modelli Razor
Nel mondo dello sviluppo per dispositivi mobili il termine "app ibrida" si riferisce in genere a un'applicazione che presenta alcune o tutte le relative schermate come pagine HTML all'interno di un controllo visualizzatore Web ospitato.
Esistono alcuni ambienti di sviluppo che consentono di compilare interamente l'app per dispositivi mobili in HTML e JavaScript, ma queste app possono subire problemi di prestazioni quando si tenta di eseguire effetti complessi di elaborazione o interfaccia utente e sono limitate anche nelle funzionalità della piattaforma a cui possono accedere.
Xamarin offre il meglio di entrambi i mondi, soprattutto quando si usa il motore di creazione modelli HTML Razor. Con Xamarin è possibile creare visualizzazioni HTML basate su più piattaforme che usano JavaScript e CSS, ma hanno anche accesso completo alle API della piattaforma sottostanti e all'elaborazione rapida con C#.
Questo documento illustra come usare il motore di modelli Razor per compilare visualizzazioni HTML+JavaScript+CSS che possono essere usate tra piattaforme mobili usando Xamarin.
Uso delle visualizzazioni Web a livello di codice
Prima di conoscere Razor, questa sezione illustra come usare le visualizzazioni Web per visualizzare direttamente il contenuto HTML, in particolare il contenuto HTML generato all'interno di un'app.
Xamarin fornisce l'accesso completo alle API della piattaforma sottostanti sia in iOS che in Android, quindi è facile creare e visualizzare HTML con C#. La sintassi di base per ogni piattaforma è illustrata di seguito.
iOS
La visualizzazione di HTML in un controllo UIWebView in Xamarin.iOS accetta anche solo alcune righe di codice:
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);
Per altre informazioni sull'uso del controllo UIWebView di iOS, vedere le ricette uiOS UIWebView.
Android
La visualizzazione di HTML in un controllo WebView con Xamarin.Android viene eseguita in poche righe di codice:
// 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);
Per altre informazioni sull'uso del controllo WebView, vedere le ricette Di Android WebView .
Specifica della directory di base
In entrambe le piattaforme è presente un parametro che specifica la directory di base per la pagina HTML. Si tratta del percorso nel file system del dispositivo usato per risolvere riferimenti relativi a risorse come immagini e file CSS. Ad esempio, tag come
<link rel="stylesheet" href="style.css" />
<img src="monkey.jpg" />
<script type="text/javascript" src="jscript.js">
fare riferimento a questi file: style.css, monkey.jpg e jscript.js. L'impostazione della directory di base indica alla visualizzazione Web in cui si trovano questi file in modo che possano essere caricati nella pagina.
iOS
Il rendering dell'output del modello viene eseguito in iOS con il codice C# seguente:
webView.LoadHtmlString (page, NSBundle.MainBundle.BundleUrl);
La directory di base viene specificata come NSBundle.MainBundle.BundleUrl
che fa riferimento alla directory in cui è installata l'applicazione. Tutti i file nella cartella Risorse vengono copiati in questo percorso, ad esempio il file style.css illustrato di seguito:
L'azione di compilazione per tutti i file di contenuto statico deve essere BundleResource:
Android
Android richiede anche che una directory di base venga passata come parametro quando le stringhe HTML vengono visualizzate in una visualizzazione Web.
webView.LoadDataWithBaseURL("file:///android_asset/", page, "text/html", "UTF-8", null);
La stringa speciale file:///android_asset/ fa riferimento alla cartella Asset Android nell'app, illustrata qui contenente il file style.css .
L'azione di compilazione per tutti i file di contenuto statico deve essere AndroidAsset.
Chiamata di C# da HTML e JavaScript
Quando una pagina HTML viene caricata in una visualizzazione Web, considera i collegamenti e i moduli come se la pagina fosse caricata da un server. Ciò significa che se l'utente fa clic su un collegamento o invia un modulo, la visualizzazione Web tenterà di passare alla destinazione specificata.
Se il collegamento è a un server esterno (ad esempio google.com), la visualizzazione Web tenterà di caricare il sito Web esterno (presupponendo che sia presente una connessione Internet).
<a href="http://google.com/">Google</a>
Se il collegamento è relativo, la visualizzazione Web tenterà di caricare il contenuto dalla directory di base. Ovviamente non è necessaria alcuna connessione di rete per il funzionamento, perché il contenuto viene archiviato nell'app nel dispositivo.
<a href="somepage.html">Local content</a>
Le azioni modulo seguono la stessa regola.
<form method="get" action="http://google.com/"></form>
<form method="get" action="somepage.html"></form>
Non si ospiterà un server Web sul client; Tuttavia, è possibile usare le stesse tecniche di comunicazione server usate nei modelli di progettazione reattivi di oggi per chiamare i servizi tramite HTTP GET e gestire le risposte in modo asincrono creando JavaScript (o chiamando JavaScript già ospitato nella visualizzazione Web). In questo modo è possibile passare facilmente i dati dal codice HTML al codice C# per l'elaborazione e quindi visualizzare nuovamente i risultati nella pagina HTML.
Sia iOS che Android forniscono un meccanismo per il codice dell'applicazione per intercettare questi eventi di spostamento in modo che il codice dell'app possa rispondere (se necessario). Questa funzionalità è fondamentale per la creazione di app ibride perché consente al codice nativo di interagire con la visualizzazione Web.
iOS
È possibile eseguire l'override dell'evento ShouldStartLoad nella visualizzazione Web in iOS per consentire al codice dell'applicazione di gestire una richiesta di navigazione, ad esempio un clic su un collegamento. I parametri del metodo forniscono tutte le informazioni
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 quindi assegnare il gestore eventi:
webView.ShouldStartLoad += HandleShouldStartLoad;
Android
In Android è sufficiente sottoclasse WebViewClient e quindi implementare il codice per rispondere alla richiesta di navigazione.
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 quindi impostare il client nella visualizzazione Web:
webView.SetWebViewClient (new HybridWebViewClient ());
Chiamata di JavaScript da C#
Oltre a indicare a una visualizzazione Web di caricare una nuova pagina HTML, il codice C# può anche eseguire JavaScript all'interno della pagina attualmente visualizzata. È possibile creare interi blocchi di codice JavaScript usando stringhe C# ed eseguire oppure è possibile creare chiamate di metodo a JavaScript già disponibili nella pagina tramite script
tag.
Android
Creare il codice JavaScript da eseguire e quindi anteporrlo a "javascript:" e indicare alla visualizzazione Web di caricare tale stringa:
var js = "alert('test');";
webView.LoadUrl ("javascript:" + js);
iOS
Le visualizzazioni Web iOS forniscono un metodo specifico per chiamare JavaScript:
var js = "alert('test');";
webView.EvaluateJavascript (js);
Riepilogo
Questa sezione ha introdotto le funzionalità dei controlli visualizzazione Web in Android e iOS che consentono di creare applicazioni ibride con Xamarin, tra cui:
- Possibilità di caricare html da stringhe generate nel codice,
- Possibilità di fare riferimento a file locali (CSS, JavaScript, Immagini o altri file HTML),
- Possibilità di intercettare le richieste di spostamento nel codice C#,
- Possibilità di chiamare JavaScript dal codice C#.
La sezione successiva presenta Razor, che semplifica la creazione del codice HTML da usare nelle app ibride.
Che cos'è Razor?
Razor è un motore di creazione modelli introdotto con ASP.NET MVC, originariamente per l'esecuzione nel server e la generazione del codice HTML da servire ai Web browser.
Il motore di modelli Razor estende la sintassi HTML standard con C# in modo da poter esprimere facilmente il layout e incorporare fogli di stile CSS e JavaScript. Il modello può fare riferimento a una classe Model, che può essere qualsiasi tipo personalizzato e le cui proprietà possono essere accessibili direttamente dal modello. Uno dei vantaggi principali è la possibilità di combinare facilmente la sintassi HTML e C#.
I modelli Razor non sono limitati all'uso lato server, ma possono anche essere inclusi nelle app Xamarin. L'uso di modelli Razor insieme alla possibilità di usare visualizzazioni Web a livello di codice consente la compilazione di applicazioni ibride multipiattaforma sofisticate con Xamarin.
Nozioni di base sul modello Razor
I file modello Razor hanno un'estensione di file con estensione cshtml . Possono essere aggiunti a un progetto Xamarin dalla sezione Creazione modelli di testo nella finestra di dialogo Nuovo file :
Di seguito è riportato un semplice modello Razor ( RazorView.cshtml).
@model string
<html>
<body>
<h1>@Model</h1>
</body>
</html>
Si notino le differenze seguenti rispetto a un normale file HTML:
- Il
@
simbolo ha un significato speciale nei modelli Razor: indica che l'espressione seguente è C# da valutare. @model
direttiva viene sempre visualizzata come prima riga di un file di modello Razor.- La
@model
direttiva deve essere seguita da un tipo. In questo esempio viene passata una stringa semplice al modello, ma potrebbe trattarsi di qualsiasi classe personalizzata. - Quando
@Model
viene fatto riferimento in tutto il modello, fornisce un riferimento all'oggetto passato al modello quando viene generato (in questo esempio sarà una stringa). - L'IDE genererà automaticamente una classe parziale per i modelli (file con estensione cshtml ). È possibile visualizzare questo codice, ma non deve essere modificato. La classe parziale è denominata RazorView in modo che corrisponda al nome del file del modello con estensione cshtml. Si tratta di questo nome usato per fare riferimento al modello nel codice C#.
@using
Le istruzioni possono essere incluse anche all'inizio di un modello Razor per includere spazi dei nomi aggiuntivi.
L'output HTML finale può quindi essere generato con il codice C# seguente. Si noti che si specifica il modello come stringa "Hello World" che verrà incorporata nell'output del modello sottoposto a rendering.
var template = new RazorView () { Model = "Hello World" };
var page = template.GenerateString ();
Di seguito è riportato l'output visualizzato in una visualizzazione Web nel simulatore iOS e nell'emulatore Android:
Altre sintassi Razor
In questa sezione verrà introdotta una sintassi Razor di base per iniziare a usarla. Gli esempi in questa sezione popolano la classe seguente con i dati e la visualizzano usando Razor:
public class Monkey {
public string Name { get; set; }
public DateTime Birthday { get; set; }
public List<string> FavoriteFoods { get; set; }
}
Tutti gli esempi usano il codice di inizializzazione dei dati seguente
var animal = new Monkey {
Name = "Rupert",
Birthday=new DateTime(2011, 04, 01),
FavoriteFoods = new List<string>
{"Bananas", "Banana Split", "Banana Smoothie"}
};
Visualizzazione delle proprietà del modello
Quando il modello è una classe con proprietà, viene facilmente fatto riferimento nel modello Razor, come illustrato in questo modello di esempio:
@model Monkey
<html>
<body>
<h1>@Model.Name</h1>
<p>Birthday: @(Model.Birthday.ToString("d MMMM yyyy"))</p>
</body>
</html>
È possibile eseguire il rendering in una stringa usando il codice seguente:
var template = new RazorView () { Model = animal };
var page = template.GenerateString ();
L'output finale viene visualizzato qui in una visualizzazione Web nel simulatore iOS e nell'emulatore Android:
Istruzioni di C#
Nel modello è possibile includere C# più complessi, ad esempio gli aggiornamenti delle proprietà Model e il calcolo age in questo esempio:
@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>
È possibile scrivere espressioni C# complesse a riga singola , ad esempio la formattazione dell'età, racchiudendo il codice con @()
.
È possibile scrivere più istruzioni C# racchiudendole con @{}
.
Istruzioni If-else
I rami di codice possono essere espressi con @if
come illustrato in questo esempio di modello.
@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>
Cicli
È anche possibile aggiungere costrutti di ciclo come foreach
. Il @
prefisso può essere usato nella variabile del ciclo ( @food
in questo caso) per eseguirne il rendering in 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>
L'output del modello precedente viene visualizzato in esecuzione nel simulatore iOS e nell'emulatore Android:
In questa sezione sono state illustrate le nozioni di base sull'uso dei modelli Razor per eseguire il rendering di visualizzazioni semplici di sola lettura. La sezione successiva illustra come creare app più complete usando Razor che possono accettare input utente e interoperabilità tra JavaScript nella visualizzazione HTML e C#.
Uso di modelli Razor con Xamarin
Questa sezione illustra come usare la compilazione di un'applicazione ibrida usando i modelli di soluzione in Visual Studio per Mac. Nella finestra Nuova >> soluzione sono disponibili tre modelli:
- Applicazione Android App > Android > WebView
- Applicazione WebView per > app iOS >
- ASP.NET progetto MVC
La finestra Nuova soluzione è simile alla seguente per i progetti i Telefono e Android, ovvero la descrizione della soluzione a destra evidenzia il supporto per il motore di creazione modelli Razor.
Si noti che è possibile aggiungere facilmente un modello Razor con estensione cshtml a qualsiasi progetto Xamarin esistente, non è necessario usare questi modelli di soluzione. I progetti iOS non richiedono uno Storyboard per l'uso di Razor; è sufficiente aggiungere un controllo UIWebView a qualsiasi visualizzazione a livello di codice ed è possibile eseguire il rendering di modelli Razor interi nel codice C#.
Il contenuto predefinito della soluzione modello per i Telefono e i progetti Android è illustrato di seguito:
I modelli offrono un'infrastruttura di applicazione pronta per caricare un modello Razor con un oggetto modello di dati, elaborare l'input dell'utente e comunicare con l'utente tramite JavaScript.
Le parti importanti della soluzione sono:
- Contenuto statico, ad esempio il file style.css .
- File modello Razor con estensione cshtml, ad esempio RazorView.cshtml .
- Classi di modello a cui viene fatto riferimento nei modelli Razor, ad esempio ExampleModel.cs .
- Classe specifica della piattaforma che crea la visualizzazione Web ed esegue il rendering del modello, ad esempio
MainActivity
in Android eiPhoneHybridViewController
in iOS.
Nella sezione seguente viene illustrato il funzionamento dei progetti.
Contenuto statico
Il contenuto statico include fogli di stile CSS, immagini, file JavaScript o altri contenuti che possono essere collegati o a cui fa riferimento un file HTML visualizzato in una visualizzazione Web.
I progetti modello includono un foglio di stile minimo per illustrare come includere contenuto statico nell'app ibrida. Il foglio di stile CSS viene fatto riferimento nel modello come segue:
<link rel="stylesheet" href="style.css" />
È possibile aggiungere qualsiasi foglio di stile e file JavaScript necessari, inclusi framework come JQuery.
Modelli cshtml Razor
Il modello include un file razor con estensione cshtml con codice predefinito per comunicare i dati tra HTML/JavaScript e C#. In questo modo è possibile creare app ibride sofisticate che non visualizzano solo i dati di sola lettura dal modello, ma accettano anche l'input dell'utente nel codice HTML e lo passano di nuovo al codice C# per l'elaborazione o l'archiviazione.
Rendering del modello
La chiamata a su un modello esegue il GenerateString
rendering del codice HTML pronto per la visualizzazione in una visualizzazione Web. Se il modello usa un modello, deve essere fornito prima del rendering. Questo diagramma illustra il funzionamento del rendering, non che le risorse statiche vengono risolte dalla visualizzazione Web in fase di esecuzione, usando la directory di base fornita per trovare i file specificati.
Chiamata di codice C# dal modello
La comunicazione da una visualizzazione Web sottoposta a rendering richiama a C# viene eseguita impostando l'URL per la visualizzazione Web e quindi intercettando la richiesta in C# per gestire la richiesta nativa senza ricaricare la visualizzazione Web.
Un esempio può essere visto nel modo in cui viene gestito il pulsante di RazorView. Il pulsante ha il codice HTML seguente:
<input type="button" name="UpdateLabel" value="Click" onclick="InvokeCSharpWithFormValues(this)" />
La InvokeCSharpWithFormValues
funzione JavaScript legge tutti i valori dal modulo HTML e imposta per location.href
la visualizzazione Web:
location.href = "hybrid:" + elm.name + "?" + qs;
Questo tentativo di spostarsi nella visualizzazione Web in un URL con uno schema personalizzato (ad esempio hybrid:
, )
hybrid:UpdateLabel?textbox=SomeValue&UpdateLabel=Click
Quando la visualizzazione Web nativa elabora questa richiesta di navigazione, è possibile intercettarla. In iOS questa operazione viene eseguita gestendo l'evento HandleShouldStartLoad di UIWebView. In Android, è sufficiente sottoclassare WebViewClient usato nel modulo ed eseguire l'override di ShouldOverrideUrlLoading.
Gli interni di questi due intercettori di navigazione sono essenzialmente gli stessi.
Prima di tutto, controllare l'URL che la visualizzazione Web sta tentando di caricare e, se non inizia con lo schema personalizzato (hybrid:
), consentire l'esecuzione normale dello spostamento.
Per lo schema URL personalizzato, tutto l'URL tra lo schema e "?" è il nome del metodo da gestire (in questo caso, "UpdateLabel"). Tutti gli elementi nella stringa di query verranno considerati come parametri per la chiamata al metodo:
var resources = url.Substring(scheme.Length).Split('?');
var method = resources [0];
var parameters = System.Web.HttpUtility.ParseQueryString(resources[1]);
UpdateLabel
in questo esempio esegue una modifica minima delle stringhe sul parametro della casella di testo (anteponendo "C# dice" alla stringa) e quindi richiama alla visualizzazione Web.
Dopo aver gestito l'URL, il metodo interrompe la navigazione in modo che la visualizzazione Web non tenti di completare l'esplorazione dell'URL personalizzato.
Modifica del modello da C#
La comunicazione con una visualizzazione Web HTML sottoposta a rendering da C# viene eseguita chiamando JavaScript nella visualizzazione Web. In iOS questa operazione viene eseguita chiamando EvaluateJavascript
in UIWebView:
webView.EvaluateJavascript (js);
In Android, JavaScript può essere richiamato nella visualizzazione Web caricando JavaScript come URL usando lo "javascript:"
schema URL:
webView.LoadUrl ("javascript:" + js);
Creazione di un'app veramente ibrida
Questi modelli non usano controlli nativi in ogni piattaforma. L'intera schermata viene riempita con una singola visualizzazione Web.
HTML può essere ideale per la creazione di prototipi e visualizzare i tipi di elementi che il Web è meglio, ad esempio rtf e layout reattivo. Tuttavia, non tutte le attività sono adatte a HTML e JavaScript: lo scorrimento di lunghi elenchi di dati, ad esempio, offre prestazioni migliori usando controlli dell'interfaccia utente nativi (ad esempio UITableView in iOS o ListView in Android).
Le visualizzazioni Web nel modello possono essere facilmente aumentate con controlli specifici della piattaforma: è sufficiente modificare MainStoryboard.storyboard usando Xcode in un Mac o Resources /layout/Main.axml in Android.
Esempio RazorTodo
Il repository RazorTodo contiene due soluzioni separate per mostrare le differenze tra un'app completamente basata su HTML e un'app che combina HTML con controlli nativi:
- RazorTodo : app completamente basata su HTML con modelli Razor.
- RazorNativeTodo : usa controlli di visualizzazione elenco nativi per iOS e Android, ma visualizza la schermata di modifica con HTML e Razor.
Queste app Xamarin vengono eseguite sia in iOS che in Android, usando librerie di classi portabili (PCL) per condividere codice comune, ad esempio le classi di database e modello. I modelli Razor .cshtml possono anche essere inclusi nella libreria di classi portabile in modo che siano facilmente condivisi tra piattaforme.
Entrambe le app di esempio incorporano le API di condivisione e sintesi vocale di Twitter dalla piattaforma nativa, dimostrando che le applicazioni ibride con Xamarin hanno ancora accesso a tutte le funzionalità sottostanti dalle visualizzazioni basate su modelli HTML Razor.
L'app RazorTodo usa modelli Razor HTML per l'elenco e modificare le visualizzazioni. Ciò significa che è possibile compilare l'app quasi completamente in una libreria di classi portabile condivisa (inclusi i modelli Razor con estensione cshtml e database cshtml ). Gli screenshot seguenti mostrano le app iOS e Android.
L'app RazorNativeTodo usa un modello Razor HTML per la visualizzazione di modifica, ma implementa un elenco di scorrimento nativo in ogni piattaforma. Ciò offre diversi vantaggi, tra cui:
- Prestazioni: i controlli di scorrimento nativi usano la virtualizzazione per garantire uno scorrimento rapido e uniforme anche con elenchi di dati molto lunghi.
- Esperienza nativa: gli elementi dell'interfaccia utente specifici della piattaforma sono facilmente abilitati, ad esempio il supporto dell'indice a scorrimento rapido in iOS e Android.
Un vantaggio fondamentale della creazione di app ibride con Xamarin è che è possibile iniziare con un'interfaccia utente completamente basata su HTML (come il primo esempio) e quindi aggiungere funzionalità specifiche della piattaforma quando necessario (come illustrato nel secondo esempio). Le schermate dell'elenco nativo e le schermate di modifica Razor HTML in iOS e Android sono illustrate di seguito.
Riepilogo
Questo articolo ha illustrato le funzionalità dei controlli visualizzazione Web disponibili in iOS e Android che facilitano la creazione di applicazioni ibride.
Ha quindi illustrato il motore di creazione modelli Razor e la sintassi che può essere usata per generare facilmente CODICE HTML nelle app Xamarin usando .file di modello Razor cshtml . Descrive anche i modelli di soluzione Visual Studio per Mac che consentono di iniziare rapidamente a creare applicazioni ibride con Xamarin.
Infine sono stati introdotti gli esempi RazorTodo che illustrano come combinare le visualizzazioni Web con interfacce utente native e API.