Création de vues HTML à l’aide de modèles Razor

Dans le monde du développement mobile, le terme « application hybride » fait généralement référence à une application qui présente une partie (ou la totalité) de ses écrans sous forme de pages HTML à l’intérieur d’un contrôle de visionneuse web hébergé.

Il existe certains environnements de développement qui vous permettent de créer votre application mobile entièrement en HTML et JavaScript, mais ces applications peuvent souffrir de problèmes de performances lors d’une tentative de traitement ou d’effets d’interface utilisateur complexes et sont également limitées dans les fonctionnalités de plateforme auxquelles elles peuvent accéder.

Xamarin offre le meilleur des deux mondes, en particulier lors de l’utilisation du moteur de création de modèles HTML Razor. Avec Xamarin, vous avez la possibilité de créer des vues HTML avec modèle multiplateforme qui utilisent JavaScript et CSS, mais vous disposez également d’un accès complet aux API de plateforme sous-jacentes et d’un traitement rapide à l’aide de C#.

Ce document explique comment utiliser le moteur de création de modèles Razor pour créer des vues HTML+JavaScript+CSS qui peuvent être utilisées sur les plateformes mobiles à l’aide de Xamarin.

Utilisation des vues web par programmation

Avant d’en savoir plus sur Razor, cette section explique comment utiliser des vues web pour afficher directement du contenu HTML, en particulier le contenu HTML généré dans une application.

Xamarin fournit un accès complet aux API de plateforme sous-jacentes sur iOS et Android. Il est donc facile de créer et d’afficher du code HTML à l’aide de C#. La syntaxe de base de chaque plateforme est illustrée ci-dessous.

iOS

L’affichage du code HTML dans un contrôle UIWebView dans Xamarin.iOS ne prend que quelques lignes de code :

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);

Pour plus d’informations sur l’utilisation du contrôle UIWebView, consultez les recettes iOS UIWebView .

Android

L’affichage du code HTML dans un contrôle WebView à l’aide de Xamarin.Android s’effectue en quelques lignes de code seulement :

// 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);

Pour plus d’informations sur l’utilisation du contrôle WebView, consultez les recettes Android WebView .

Spécification du répertoire de base

Sur les deux plateformes, il existe un paramètre qui spécifie le répertoire de base de la page HTML. Il s’agit de l’emplacement du système de fichiers de l’appareil utilisé pour résoudre les références relatives aux ressources telles que les images et les fichiers CSS. Par exemple, des balises telles que

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

reportez-vous à ces fichiers : style.css, monkey.jpg et jscript.js. Le paramètre de répertoire de base indique à la vue web où se trouvent ces fichiers afin qu’ils puissent être chargés dans la page.

iOS

La sortie du modèle est rendue dans iOS avec le code C# suivant :

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

Le répertoire de base est spécifié comme NSBundle.MainBundle.BundleUrl faisant référence au répertoire dans lequel l’application est installée. Tous les fichiers du dossier Resources sont copiés à cet emplacement, par exemple le fichier style.css illustré ici :

Solution iPhoneHybrid

L’action de génération pour tous les fichiers de contenu statiques doit être BundleResource :

Action de génération de projet iOS : BundleResource

Android

Android nécessite également qu’un répertoire de base soit passé en tant que paramètre lorsque des chaînes html sont affichées dans une vue web.

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

La chaîne spéciale file:///android_asset/ fait référence au dossier Ressources Android dans votre application, qui contient le fichier style.css .

Solution AndroidHybrid

L’action de génération pour tous les fichiers de contenu statiques doit être AndroidAsset.

Action de génération de projet Android : AndroidAsset

Appel de C# à partir de HTML et JavaScript

Lorsqu’une page html est chargée dans une vue web, elle traite les liens et les formulaires comme si la page était chargée à partir d’un serveur. Cela signifie que si l’utilisateur clique sur un lien ou envoie un formulaire, la vue web tente d’accéder à la cible spécifiée.

Si le lien est vers un serveur externe (par exemple, google.com), la vue web tente de charger le site web externe (en supposant qu’il existe une connexion Internet).

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

Si le lien est relatif, la vue web tente de charger ce contenu à partir du répertoire de base. Évidemment, aucune connexion réseau n’est requise pour que cela fonctionne, car le contenu est stocké dans l’application sur l’appareil.

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

Les actions de formulaire suivent la même règle.

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

Vous n’allez pas héberger de serveur web sur le client ; Toutefois, vous pouvez utiliser les mêmes techniques de communication de serveur que celles utilisées dans les modèles de conception réactifs d’aujourd’hui pour appeler des services via HTTP GET et gérer les réponses de manière asynchrone en émettant du Code JavaScript (ou en appelant JavaScript déjà hébergé dans la vue web). Cela vous permet de transmettre facilement des données du code HTML au code C# pour traitement, puis d’afficher les résultats dans la page HTML.

iOS et Android fournissent un mécanisme permettant au code d’application d’intercepter ces événements de navigation afin que le code d’application puisse répondre (si nécessaire). Cette fonctionnalité est essentielle à la création d’applications hybrides, car elle permet au code natif d’interagir avec la vue web.

iOS

L’événement ShouldStartLoad sur la vue web dans iOS peut être remplacé pour permettre au code d’application de gérer une demande de navigation (par exemple, un clic sur un lien). Les paramètres de la méthode fournissent toutes les informations

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

puis affectez le gestionnaire d’événements :

webView.ShouldStartLoad += HandleShouldStartLoad;

Android

Sur Android, il suffit de sous-classer WebViewClient, puis d’implémenter du code pour répondre à la demande de navigation.

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
    }
}

puis définissez le client sur la vue web :

webView.SetWebViewClient (new HybridWebViewClient ());

Appel de JavaScript à partir de C#

En plus d’indiquer à une vue web de charger une nouvelle page HTML, le code C# peut également exécuter JavaScript dans la page actuellement affichée. Des blocs de code JavaScript entiers peuvent être créés à l’aide de chaînes C# et exécutés, ou vous pouvez créer des appels de méthode vers JavaScript déjà disponibles sur la page via script des balises.

Android

Créez le code JavaScript à exécuter, puis préfixez-le avec « javascript: » et indiquez à la vue web de charger cette chaîne :

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

iOS

Les vues web iOS fournissent une méthode spécifique pour appeler JavaScript :

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

Résumé

Cette section présente les fonctionnalités des contrôles d’affichage web sur Android et iOS qui nous permettent de créer des applications hybrides avec Xamarin, notamment :

  • La possibilité de charger du code HTML à partir de chaînes générées dans le code,
  • La possibilité de référencer des fichiers locaux (CSS, JavaScript, Images ou autres fichiers HTML),
  • La possibilité d’intercepter les demandes de navigation dans le code C#,
  • Possibilité d’appeler JavaScript à partir de code C#.

La section suivante présente Razor, qui facilite la création du code HTML à utiliser dans les applications hybrides.

Présentation de Razor

Razor est un moteur de création de modèles qui a été introduit avec ASP.NET MVC, à l’origine pour s’exécuter sur le serveur et générer du code HTML à servir aux navigateurs web.

Le moteur de création de modèles Razor étend la syntaxe HTML standard avec C# afin que vous puissiez exprimer la disposition et incorporer facilement des feuilles de style CSS et JavaScript. Le modèle peut référencer une classe Model, qui peut être n’importe quel type personnalisé et dont les propriétés sont accessibles directement à partir du modèle. L’un de ses main avantages est la possibilité de mélanger facilement les syntaxes HTML et C#.

Les modèles Razor ne sont pas limités à une utilisation côté serveur, ils peuvent également être inclus dans les applications Xamarin. L’utilisation de modèles Razor et la possibilité d’utiliser des vues web par programmation permet de créer des applications hybrides multiplateformes sophistiquées avec Xamarin.

Concepts de base du modèle Razor

Les fichiers de modèle Razor ont une extension de fichier .cshtml . Ils peuvent être ajoutés à un projet Xamarin à partir de la section Création de modèles de texte de la boîte de dialogue Nouveau fichier :

Nouveau fichier - Modèle Razor

Un modèle Razor simple ( RazorView.cshtml) est illustré ci-dessous.

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

Notez les différences suivantes par rapport à un fichier HTML standard :

  • Le @ symbole a une signification spéciale dans les modèles Razor : il indique que l’expression suivante est C# à évaluer.
  • @model directive apparaît toujours en tant que première ligne d’un fichier de modèle Razor.
  • La @model directive doit être suivie d’un Type. Dans cet exemple, une chaîne simple est passée au modèle, mais il peut s’agir de n’importe quelle classe personnalisée.
  • Quand @Model est référencé dans tout le modèle, il fournit une référence à l’objet passé au modèle lorsqu’il est généré (dans cet exemple, il s’agit d’une chaîne).
  • L’IDE génère automatiquement une classe partielle pour les modèles (fichiers avec l’extension .cshtml ). Vous pouvez afficher ce code, mais il ne doit pas être modifié. RazorView.cshtml La classe partielle est nommée RazorView pour correspondre au nom du fichier de modèle .cshtml. C’est ce nom qui est utilisé pour faire référence au modèle dans le code C#.
  • @using les instructions peuvent également être incluses en haut d’un modèle Razor pour inclure des espaces de noms supplémentaires.

La sortie HTML finale peut ensuite être générée avec le code C# suivant. Notez que nous spécifions le modèle comme une chaîne « Hello World » qui sera incorporée dans la sortie du modèle rendu.

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

Voici la sortie affichée dans une vue web sur le simulateur iOS et l’émulateur Android :

Hello World

Plus de syntaxe Razor

Dans cette section, nous allons présenter une syntaxe Razor de base pour vous aider à commencer à l’utiliser. Les exemples de cette section renseignent la classe suivante avec des données et les affichent à l’aide de Razor :

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

Tous les exemples utilisent le code d’initialisation des données suivant

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

Affichage des propriétés du modèle

Lorsque le modèle est une classe avec des propriétés, elles sont facilement référencées dans le modèle Razor, comme illustré dans cet exemple de modèle :

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

Il peut être rendu dans une chaîne à l’aide du code suivant :

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

La sortie finale s’affiche ici dans une vue web sur le simulateur iOS et l’émulateur Android :

Rupert

Instructions C#

Vous pouvez inclure des C# plus complexes dans le modèle, comme les mises à jour de la propriété Model et le calcul Age dans cet exemple :

@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>

Vous pouvez écrire des expressions C# monoligne complexes (comme la mise en forme de l’âge) en entourant le code avec @().

Plusieurs instructions C# peuvent être écrites en les entourant avec @{}.

Instructions If-else

Les branches de code peuvent être exprimées avec @if , comme indiqué dans cet exemple de modèle.

@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>

Boucles

Des constructions de boucle telles que foreach peuvent également être ajoutées. Le @ préfixe peut être utilisé sur la variable de boucle ( @food dans ce cas) pour l’afficher en 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>

La sortie du modèle ci-dessus s’affiche en cours d’exécution sur le simulateur iOS et l’émulateur Android :

Rupert X Monkey

Cette section a couvert les principes de base de l’utilisation de modèles Razor pour afficher des vues en lecture seule simples. La section suivante explique comment créer des applications plus complètes à l’aide de Razor qui peuvent accepter l’entrée utilisateur et interagir entre JavaScript dans la vue HTML et C#.

Utilisation de modèles Razor avec Xamarin

Cette section explique comment utiliser la génération de votre propre application hybride à l’aide des modèles de solution dans Visual Studio pour Mac. Trois modèles sont disponibles dans la fenêtre Fichier > Nouvelle > solution... :

  • Android > App > Android WebView Application
  • Application WebView iOS >>
  • ASP.NET projet MVC

La fenêtre Nouvelle solution ressemble à ceci pour les projets iPhone et Android. La description de la solution à droite met en évidence la prise en charge du moteur de création de modèles Razor.

Création de solutions iPhone et Android

Notez que vous pouvez facilement ajouter un modèle Razor .cshtml à n’importe quel projet Xamarin existant. Il n’est pas nécessaire d’utiliser ces modèles de solution. Les projets iOS ne nécessitent pas non plus de Storyboard pour utiliser Razor ; Ajoutez simplement un contrôle UIWebView à n’importe quelle vue par programmation et vous pouvez restituer des modèles Razor entiers en code C#.

Le contenu de la solution de modèle par défaut pour les projets iPhone et Android est illustré ci-dessous :

Modèles iPhone et Android

Les modèles vous offrent une infrastructure d’application prête à l’utilisation pour charger un modèle Razor avec un objet de modèle de données, traiter l’entrée utilisateur et communiquer avec l’utilisateur via JavaScript.

Les parties importantes de la solution sont les suivantes :

  • Contenu statique tel que le fichier style.css .
  • Fichiers de modèle Razor .cshtml tels que RazorView.cshtml .
  • Classes de modèle référencées dans les modèles Razor tels que ExampleModel.cs .
  • Classe spécifique à la plateforme qui crée la vue web et affiche le modèle, par MainActivity exemple sur Android et iPhoneHybridViewController sur iOS.

La section suivante explique le fonctionnement des projets.

Contenu statique

Le contenu statique inclut des feuilles de style CSS, des images, des fichiers JavaScript ou d’autres contenus qui peuvent être liés ou référencés par un fichier HTML affiché dans une vue web.

Les projets de modèle incluent une feuille de style minimale pour montrer comment inclure du contenu statique dans votre application hybride. La feuille de style CSS est référencée dans le modèle comme suit :

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

Vous pouvez ajouter les fichiers de feuille de style et JavaScript dont vous avez besoin, y compris les frameworks comme JQuery.

Modèles Razor cshtml

Le modèle inclut un fichier Razor .cshtml qui a du code préécrit pour faciliter la communication des données entre html/JavaScript et C#. Cela vous permettra de créer des applications hybrides sophistiquées qui n’affichent pas seulement les données en lecture seule à partir du modèle, mais acceptent également l’entrée utilisateur dans le code HTML et les transmettent au code C# pour le traitement ou le stockage.

Affichage du gabarit

L’appel de sur GenerateString un modèle rend le code HTML prêt à être affiché dans une vue web. Si le modèle utilise un modèle, il doit être fourni avant le rendu. Ce diagramme illustre le fonctionnement du rendu, et non pas le fait que les ressources statiques soient résolues par la vue web au moment de l’exécution, à l’aide du répertoire de base fourni pour rechercher les fichiers spécifiés.

Organigramme Razor

Appel du code C# à partir du modèle

La communication à partir d’une vue web rendue appelant vers C# s’effectue en définissant l’URL de la vue web, puis en interceptant la requête en C# pour gérer la requête native sans recharger la vue web.

Un exemple peut être vu dans la façon dont le bouton de RazorView est géré. Le bouton a le code HTML suivant :

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

La InvokeCSharpWithFormValues fonction JavaScript lit toutes les valeurs du formulaire HTML et définit le location.href pour la vue web :

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

Cela tente de naviguer dans la vue web jusqu’à une URL avec un schéma personnalisé (par exemple, hybrid:)

hybrid:UpdateLabel?textbox=SomeValue&UpdateLabel=Click

Lorsque la vue web native traite cette demande de navigation, nous avons la possibilité de l’intercepter. Dans iOS, cela s’effectue en gérant l’événement HandleShouldStartLoad d’UIWebView. Dans Android, nous nous contentons de sous-classer le WebViewClient utilisé dans le formulaire et de remplacer ShouldOverrideUrlLoading.

Les éléments internes de ces deux intercepteurs de navigation sont essentiellement les mêmes.

Tout d’abord, case activée l’URL que la vue web tente de charger et, si elle ne commence pas par le schéma personnalisé (hybrid:), autorisez la navigation à se produire normalement.

Pour le schéma d’URL personnalisé, tout ce qui se trouve dans l’URL entre le schéma et le « ? » est le nom de la méthode à gérer (dans ce cas, « UpdateLabel »). Tous les éléments de la chaîne de requête sont traités comme les paramètres de l’appel de méthode :

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

UpdateLabel dans cet exemple effectue une manipulation de chaîne minimale sur le paramètre de zone de texte (en attendant « C# dit » à la chaîne), puis rappelle la vue web.

Après avoir géré l’URL, la méthode abandonne la navigation afin que la vue web ne tente pas de terminer la navigation vers l’URL personnalisée.

Manipulation du modèle à partir de C#

La communication vers une vue web HTML rendue à partir de C# s’effectue en appelant JavaScript dans la vue web. Pour ce faire, sur iOS, appelez EvaluateJavascript le UIWebView :

webView.EvaluateJavascript (js);

Sur Android, JavaScript peut être appelé dans la vue web en chargeant javaScript en tant qu’URL à l’aide du schéma d’URL "javascript:" :

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

Rendre une application vraiment hybride

Ces modèles n’utilisent pas de contrôles natifs sur chaque plateforme : l’écran entier est rempli d’une seule vue web.

Le code HTML peut être idéal pour le prototypage et l’affichage des types d’éléments que le web est le mieux, comme le texte enrichi et la mise en page réactive. Toutefois, toutes les tâches ne sont pas adaptées au CODE HTML et à JavaScript. Par exemple, le défilement de longues listes de données s’effectue mieux à l’aide de contrôles d’interface utilisateur natifs (tels que UITableView sur iOS ou ListView sur Android).

Les vues web dans le modèle peuvent facilement être augmentées avec des contrôles spécifiques à la plateforme : il suffit de modifier mainStoryboard.storyboard à l’aide de Xcode sur un Mac ou de Resources/layout/Main.axml sur Android.

Exemple RazorTodo

Le référentiel RazorTodo contient deux solutions distinctes pour montrer les différences entre une application entièrement pilotée par html et une application qui combine du code HTML avec des contrôles natifs :

  • RazorTodo : application entièrement pilotée par HTML à l’aide de modèles Razor.
  • RazorNativeTodo : utilise des contrôles d’affichage de liste natifs pour iOS et Android, mais affiche l’écran d’édition avec HTML et Razor.

Ces applications Xamarin s’exécutent à la fois sur iOS et Android, utilisant des bibliothèques de classes portables (PCL) pour partager du code commun, comme les classes de base de données et de modèle. Les modèles Razor .cshtml peuvent également être inclus dans la LCP afin d’être facilement partagés entre les plateformes.

Les deux exemples d’applications intègrent le partage Twitter et les API de synthèse vocale à partir de la plateforme native, ce qui montre que les applications hybrides avec Xamarin ont toujours accès à toutes les fonctionnalités sous-jacentes à partir des vues basées sur des modèles Razor HTML.

L’application RazorTodo utilise des modèles Html Razor pour les vues de liste et de modification. Cela signifie que nous pouvons générer l’application presque entièrement dans une bibliothèque de classes portable partagée (y compris la base de données et les modèles Razor .cshtml ). Les captures d’écran ci-dessous montrent les applications iOS et Android.

RazorTodo

L’application RazorNativeTodo utilise un modèle Razor HTML pour la vue d’édition, mais implémente une liste de défilement native sur chaque plateforme. Cela offre un certain nombre d’avantages, notamment :

  • Performances : les contrôles de défilement natifs utilisent la virtualisation pour garantir un défilement rapide et fluide, même avec de très longues listes de données.
  • Expérience native : les éléments d’interface utilisateur spécifiques à la plateforme sont facilement activés, tels que la prise en charge de l’index à défilement rapide dans iOS et Android.

L’un des principaux avantages de la création d’applications hybrides avec Xamarin est que vous pouvez commencer avec une interface utilisateur entièrement pilotée par html (comme le premier exemple), puis ajouter des fonctionnalités spécifiques à la plateforme si nécessaire (comme le montre le deuxième exemple). Les écrans de liste natifs et les écrans d’édition HTML Razor sur iOS et Android sont présentés ci-dessous.

RazorNativeTodo

Résumé

Cet article explique les fonctionnalités des contrôles d’affichage web disponibles sur iOS et Android qui facilitent la création d’applications hybrides.

Il a ensuite abordé le moteur de création de modèles Razor et la syntaxe qui peut être utilisée pour générer facilement du code HTML dans les applications Xamarin à l’aide de . cshtml Fichiers de modèle Razor. Il décrit également les modèles de solution Visual Studio pour Mac qui vous permettent de commencer rapidement à créer des applications hybrides avec Xamarin.

Enfin, il a introduit les exemples RazorTodo qui montrent comment combiner des vues web avec des interfaces utilisateur natives et des API.