Préface: L'article précédent présente l'encapsulation de l'addition, de la suppression, de la modification et de la recherche de KO, ce qui économise en effet beaucoup de code JS. Le blogueur est une personne qui aime être paresseuse. Il estime toujours que ces ajouts de base, suppressions, modifications et vérifications peuvent générer directement des effets de page via un outil, et aucun code n'est nécessaire. Ce serait tellement cool. J'ai donc étudié la grammaire de T4. Bien que je ne l'ai pas complètement maîtrisé, j'avais une compréhension générale. Donc, l'article d'aujourd'hui: Générez rapidement des pages à travers des modèles T4.
Articles Knockoutjs Series:
Bootstraptable et knockoutjs se combinent pour atteindre la fonction d'ajout, de supprimer, de modifier et de vérifier [1]
Bootstraptable et knockoutjs se combinent pour atteindre la fonction d'ajout, de supprimer, de modifier et de vérifier [2]
Bootstraptable + knockoutjs se combine pour réaliser la solution d'ajout, de suppression, de modification et de vérification (3) Deux vues de vue peuvent compléter l'addition, la suppression, la modification et la vérification
1. Introduction à l'utilisation de T4
Nous savons que lors de l'ajout de vues dans MVC, l'effet de la page de l'ajout, de la suppression, de la modification et de la vérification peut être généré automatiquement. En effet, MVC a des modèles de base intégrés pour ajouter, supprimer, modifier et vérifier. La syntaxe de ces modèles est d'utiliser T4, alors où sont ces modèles? Après avoir recherché des articles connexes, j'ai constaté que l'emplacement des modèles de version MVC4 et ci-dessous est très différent de celui de MVC5 et supérieur.
• Emplacement du modèle pour MVC4 et les versions suivantes: VS Directory d'installation + / itemTemplates / CSharp / Web / MVC 2 / Codeemplates. Par exemple, les fichiers d: / programme du blogueur (x86) / Microsoft Visual Studio 12.0 / Common7 / IDE / ItemTemplates / CSharp / Web / MVC 4 / Codeemplates.
Recherchez le modèle correspondant à CSHTML, et il existe des fichiers TT correspondants qui ajoutent, suppriment, modifier et vérifier
• MVC5 et au-dessus de l'emplacement du modèle: Donnez directement l'emplacement du modèle du blogueur D: / Program Files (X86) / Microsoft Visual Studio 12.0 / Common7 / IDE / Extensions / Microsoft / Web / MVC / Scafolding / Modèles
Une fois que vous le savez, l'étape suivante consiste à rénover le modèle et à ajouter votre propre contenu généré. Vous pouvez copier directement la liste et modifier des modèles à la transformation de l'auto-transformation, mais après y avoir pensé, il vaut mieux ne pas toucher le MVC intégré. Il n'est pas préférable de construire vous-même vos propres modèles.
Créez un nouveau dossier sous le répertoire racine du projet Web actuel, nommez IT Codeemplates, puis copiez les deux dossiers de modèles MVCControlleRempty et MVCView dans le modèle MVC dans le dossier Codeemplates, comme indiqué ci-dessous:
De cette façon, lorsque nous ajoutons un nouveau contrôleur et créons une nouvelle vue, nous pouvons voir notre modèle personnalisé:
2. Introduction du code T4
Ce qui précède introduit comment créer votre propre modèle. Une fois le modèle construit, vous devez commencer à enfiler le contenu correspondant. Si la grammaire de T4 est élargie, cet article sera sans fin. Les jardiniers intéressés peuvent rechercher dans le jardin. Il y a encore beaucoup d'articles. Jetons un coup d'œil à quelques contenus de modèle ici. Une autre chose à noter est qu'il semble qu'après MVC5, le suffixe de fichier de modèle de T4 a été changé en T4, et les modèles précédents se sont toujours terminés avec TT. Sans regarder les différences dans leur syntaxe, on estime qu'il devrait y avoir peu de différence.
1. Controller.Cs.T4
Pourquoi réécrire ce modèle de contrôleur vide? Le blogueur pense que de nombreuses méthodes d'ajout, de supprimer, de modifier et de vérifier doivent être écrites manuellement et c'est beaucoup de mal à écrire un modèle directement. Jetons un coup d'œil au code d'implémentation dans le modèle:
<# @ template Language = "C #" hostSpecific = "true" #> <# @ output extension = "cs" #> <# @ paramètre type = "System.String" name = "ContrônerName" #> <@ @ paramètre type = "System.string" Name = "ControlerRootName" #> <# @ paramètre Type = "System.String" Name = "nom name = "Areaname" #> <# var index = ContrônerName.LastIndexof ("Controller"); var ModelName = ControlnerName.SubString (0, index); #> Utilisation du système; Utilisation de System.Collections.Generic; Utilisation de System.Linq; Utilisation de System.Web; : Controller {public ActionResult Index () {return View ();} public ActionResult Edit (<# = modelName #> modèle) {return View (modèle);} [httpget] public JSonResult get (int limit, int offset) {return json (new {}, jsonrequestbehavior.allowget);} // ajouter entité [httppost] public. Add (<# = ModelName #> odata) {<# = modelName #> Model.Add (odata); return JSON (new {}, jsonrequestbehavior.allowget);} // Update Entity [httppost] public JsonResult Update (<# = modelname #> odata) {<# = modelname #> Model.update (odata); {}, Jsonrequestbehavior.allowget);} // delete entité [httppost] public jsonResult Delete (list << # = modelName #> odata) {<# = modelName #> Model.delete (odata); return json (new {}, jsonrequestbehavior.allowget);}}Ce contenu n'est pas difficile à comprendre. Vérifiez simplement le code du contrôleur généré:
Utilisation du System; Utilisation de System.Collections.Generic; Utilisation de System.Linq; Utilisation de System.Web; Utilisation de System.Web.Mvc; Utilisation de TestKo.Models; Namespace Testko.Controllers {Return View ();} public ActionSult EditSult) Get (int limit, int offset) {return json (new {}, jsonRequestBehavior.Allowget);} // add entité [httppost] public JSonResult add (user odata) {userModel.add (odata); return JSON (new {}, jsonRequestBehavior.Allowget);} // Update Entity [httppost] public JsonResult Update (user odata) {userModel.update (odata); return JSON (new {}, jsonRequestBehavior.Allowget);} // delete entité [httppost] public JSonResult Delete (list <user> odata) {userModel.delete (odata); return json (new {}, jsonrequestbehavior.allowget);}}}2. Koindex.cs.t4
Ce modèle est principalement utilisé pour générer des pages de liste, avec le code général comme suit:
<# @ Template Language = "C #" hostSpecific = "true" #> <# @ output extension = ". cshtml" #> <# @ include file = "import.include.t4" #> <# // La vue de silence suivante sort le code d'en-tête de fichier et la marque pour une vue partielle, une vue en utilisant une page de mise en page, ou une vue régulière.If (isPartialView) {# # # if (islayoutPageSelected) {#> @ {Viewbag.title = "<# = ViewName #>"; <# if (! string.isnullorempty (LayoutPageFile)) {#> Layout = "<# = LayoutPagefile #>"; <#} #>} <#} else {#> @ @ {Layout = Null;} <! html> <html> <éadf> <meta name = "Viewport" contenu = "width = device-width" /> <title> <# = ViewName #> </ title> <link href = "~ / contenu / bootstrap / css / link href = "~ / contenu / bootstrap-table / bootstrap-table.min.css" rel = "Stylesheet" /> <script src = "~ / scripts / jQuery-1.9.1.min.js"> </ script> <script src = "~ / contenu / boootstrap / js / bootstrap.min.js"> </ script> src = "~ / contenu / bootstrap-table / bootstrap-table.min.js"> </ script> <script src = "~ / contenu / bootstrap-teable / locale / bootstrap-table-zh-cn.js"> </ script> <script src = "~ / scripts / knockout-3.4.0.min.js"> </ script> src = "~ / scripts / knockout / extensions / knockout.mapping-latest.js"> </ script> <script src = "~ / scripts / extensions / knockout.index.js"> </ script> <script src = "~ / scripts / extensions / knockout.index.js"> </cript> <cript src = "~ / scripts / extensions / knockout.index.js"> </ script> <script src = "~ / scripts / extensions / knockout.bootstraptable.js"> </ script> <script type = "text / javascrip "/ <# = ViewDatatyPeshortName #> / get", pagesize: 2,}, URLS: {del: "/ <# = ViewDataTyPeshortName #> / delete", édition: "/ <# = ViewDataTyPeshortName #> / edit", add: "/ <# = vue : {}}; ko.bindingViewModel (ViewModel);}); </script> </ head> <body> <# pushindent ("");} #> <div id = "Toolbar"> <Button Data-Bind = "Click: AddClick" Type = "Button"> <pander aria-hidden = "True"> </pank Type = "Button"> <span Aria-Hidden = "true"> </ span> Modifier </futton> <Button Data-Bind = "Click: DeleteClick" Type = "Button"> <span Aria-Hidden = "true"> </ span> delete </ Button> </div> <Table Data-Bind = "bootstraptable: bootstaptable"> <tr> <Tr> <Table Data-Checkbox = "true"> </ th> <# ienumerable <propriétéMetAdata> Properties = ModelMetAdata.Properties; ForEach (PropertyMetAdata Property in Properties) {if (propriété.Scafold &&! GetValueExpression (propriété) #> </ th> <#}} #> </tr> </thead> </ table> <# // Le code suivant ferme la balise utilisée dans le cas d'une vue en utilisant une page de mise en page et les balises corporelles et html dans le cas d'une page de vue régulière #> <# if (! ISpartialView &&! IslayoutPageSeled) {Clearindent (); #> </body> </html> <#} #> <# @ include File = "ModelMetAdatafunctions.cs.include.t4" #>Ajouter un index de vue et sélectionner ce modèle
Le contenu de la page obtenu
@ {Layout = null;} <! Doctype html> <html> <adref> <meta name = "Viewport" contenu = "width = device-width" /> <itle> index </ title> <link href = "~ / contenu / bootstrap / csss / bootstrap.min.css" rel = "Styleet" /> <lien " href = "~ / contenu / bootstrap-table / bootstrap-table.min.css" rel = "Stylesheet" /> <script src = "~ / scripts / jQuery-1.9.1.min.js"> </ script> <script src = "~ / contenu / boootstrap / js / bootstrap.min.js"> </ script> src = "~ / contenu / bootstrap-table / bootstrap-table.min.js"> </ script> <script src = "~ / contenu / bootstrap-teable / locale / bootstrap-table-zh-cn.js"> </ script> <script src = "~ / scripts / knockout-3.4.0.min.js"> </ script> src = "~ / scripts / knockout / knockout-3.4.0.min.js"> </ script> <script src = "~ / scripts / knockout / extensions / knockout.mapping-latest.js"> </ script> <script src = "~ / scripts / extensions / knockout.index.js"> </cript> <prit> <prit> src = "~ / scripts / extensions / knockout.bootstraptable.js"> </ script> <script type = "text / javascrip "/ User / edit", ajouter: "/ user / edit",}, queryCondition: {}}; ko.bindingViewModel (ViewModel);}); </ script> </ head> <body> <div id = "Toolbar"> <Button Data-Bind = "Click: AddClick" Type = "Button"> <pan Span Aria-Hidden = "TRUE"> <pander> data-bind = "cliquez: editclick" type = "bouton"> <span aria-hidden = "true"> </span> modifier </sponte> <bouton data-bind = "cliquez: deleteclick" type = "bouton"> <span aria-hidden = "true"> </ span> delete </sponte> </v> <Table Data-Bind = "BootStrapable: BootStRaptable"> <tr> Data-Checkbox = "true"> </ th> <th data-field = "name"> name </ th> <th data-field = "fullname"> fullname </th> <th data-field = "age"> Âge </ th> <th data-field = "des"> des </th> <th data-find = "Createtime"> Createtime </th> <th> <t Data-Field = "StrCreateTime"> StrCreateTime </th> </tr> </thEad> </ Table> </ Body> </Html> INDEX.CSHTMLNous avons déplacé le ViewModel mentionné dans l'article précédent vers la page, afin que nous n'ayons pas à le passer du contrôleur à chaque fois. Modifiez légèrement le nom de la colonne de la table et la page peut s'exécuter.
Voici quelques points à optimiser:
(1) Les conditions de requête n'ont pas été générées. Si vous étudiez la syntaxe de T4 un peu plus profondément, vous pouvez ajouter des caractéristiques aux champs qui doivent être interrogés pour identifier les champs doivent être interrogés, puis générer automatiquement les conditions de requête correspondantes.
(2) Les noms de colonne de la table semblent être générés via les propriétés de champ de l'attribut. Ceci est similaire au premier point, et les deux doivent étudier la grammaire de T4.
3. Koedit.cs.t4
La troisième page de modèle est le modèle édité, et son code brut est le suivant:
<# @ Template Language = "C #" hostSpecific = "true" #> <# @ output extension = ". cshtml" #> <# @ include file = "import.include.t4" #> @ modèle <# = ViewDatatyPename #> <# // "Form-Control" Attribute est unique a div in Bootstrapstring boolType = "System.Boolean";Version requiredMvcVersion = new Version("5.1.0.0");bool isControlHtmlAttributesSupported = MvcVersion >= requiredMvcVersion;// The following chained if-statement outputs the file header code and markup for a partial view, a view using a layout page, or a regular View.if (isPartialView) {#> <#} else if (islayoutPageSelected) {#> @ {Viewbag.Title = "<# = ViewName #>"; <# if (! string.isnullorempty (LayoutPageFile)) {#> Layout = "<# = LayoutPageFile #>"; ViewName #> </h2> <#} else {#> @ {Layout = null;} <! Doctype html> <html> <ead> <meta name = "Viewport" contenu = "width = device-width" /> <title> <# = Viewname #> </t titre> </-head> <body> <# pushIndent (");} #> <# if (if (if (body> <# pushSend (");} {#> <# if (! IslayoutPageSelected && isBundleConfigpresent) {#> @ scripts.render ("~ / bundles / jQuery") @ scripts.render ("~ / bundles / jQueryval") <#} #> <# else if (! islayoutPageSected) {#> < src = "~ / scripts / jQuery - <# = jQueryversion #>. min.js"> </ script> <script src = "~ / scripts / jQuery.validate.min.js"> </ script> <script src = "~ / scripts / jquery.validate.unobtrusive.min.js"> </ script> id = "Formedit"> @ html.hiddenfor (Model => Model.id) <v> <# ienumerable <propriétéMetAdata> Properties = ModelMetAdata.Properties; ForEach (propriété PropertyMetAdata dans Properties) {if (Property.sffold &&! Property.SpriMaryKey &&! Property.isforeignkey) {#> <div> @ html.Labelfor (modèle => modèle. <# = getValueExpression (propriété) #>, "<# = getValueExpression (propriété) #>", new {@class = "Control-Label Col-xs-2"}) <v> @ html.textboxFor (modèle => modèle. = "form-control", data_bind = "value: editmodel. <# = getValueExpression (propriété) #>"}) </ div> </ div> <#}} #> </ div> <v> <Button Type = "Button" Data-Dismiss = "Modal"> <span Aria-Hidden = "True"> </pank> Certe aria-hidden = "true"> </span> Enregistrer </button> </div> </ form> <# var index = ViewDatatyName.LastIndexof ("."); var ModelName = ViewDatatyPename.SubString (index + 1, ViewDatyPename.Lengthre src = "~ / scripts / extensions / knockout.edit.js"> </ script> <script type = "text / javascrip Model.id == 0? }); </ script> <# if (islayoutPageSelected && référencescriptBiBrary && isBundleConfigpresent) {#> @ section scripts {@ scripts.render ("~ / bundles / jQueryval")} <#} #> <# else if (IslayoutPageSeled && regencescriptLibrarys) {#> <script src = "~ / scripts / jQuery - <# = jQueryversion #>. min.js"> </ script> <script src = "~ / scripts / jQuery.validate.min.js"> </ script> <script src = "~ / scripts / jQuery.valida.unobtrusive.min.js"> </ script> src = "~ / scripts / jquery.validate.unobtrusive.min.js"> </ script> <#} #> <# // Le code suivant ferme la balise utilisée dans le cas d'une vue en utilisant une page de mise en page et les balises corporelles et html dans le cas d'une page de vue régulière #> <# if (! isPartialView &&! IslayoutPageSeled) {Clearindent (); #> </body> </html> <#} #> <# @ include File = "ModelMetAdatafunctions.cs.include.t4" #>Code généré:
@model testko.models.user <form id = "Formedit"> @ html.hiddenfor (modèle => modèle.id) <v> <v> @ html.labelfor (modèle => Model.name, "name", new {@class = "Control-Label Col-xs-2"}) <div> @ html.textBoxFor (Model => Model.name. @class = "form-control", data_bind = "value: editmodel.name"}) </div> </div> <v> @ html.labelfor (modèle => Model.fullnname, "fullName", new {@class = "Control-Label Col-Xs-2"}) <div> @ html.text @class = "form-control", data_bind = "value: editmodel.fullname"}) </div> </div> <v> @ html.labelfor (modèle => Model.age, "Age", new {@class = "Control-Label Col-xs-2"}) <v> @ html.textBoxOrt "form-control", data_bind = "value: editmodel.age"}) </div> </div> <v> @ html.labelfor (Model => Model.des, "DES", nouveau {@class = "Control-Label Col-xs-2"}) <v> @ html.textboxfor (Model => Model.Des, new {New {Form = "FORM-CONFORT" data_bind = "Value: editmodel.des"}) </div> </div> <div> @ html.labelfor (modèle => Model.CreateTime, "CreateTime", new {@class = "Control-Label Col-XS-2"}) <div> @ html.textBoxFor (Model => Model.Createtime, New {@class = "Form-ControL" data_bind = "Value: editModel.CreateTime"}) </div> </div> <div> @ html.labelfor (Model => Model.strcreateTime, "StrecreateEtime", new {@class = "Control-Label Col-XS-2"}) <v> @ html.textBoxFor (Model => Model.StrcreateETiM "form-control", data_bind = "value: editmodel.strcreateetime"}) </div> </div> <div> <bouton type = "Button" Data-Dismiss = "modal"> <span aria-hidden = "true"> </ span> close </ bouton> <bouton type = "soumis"> <span Aria-Hidden = "true"> </ span> Enregistrer </ Button> </div> </form> <Script Src = "~ / Scripts / Extensions / Knockout.edit.js"> </script> <Script Type = "Text / Javascript"> $ (fonction () {var Model = @ Html.Raw (NewTonsoft.Json.Json ViewModel = {Formid: "Formedit", editModel: modèle, URLS: {soumis: modèle.id == 0? '}}}}}}}; ko.bindingEditViewModel (ViewModel);Bien sûr, le code doit également être légèrement modifié. En ajoutant une page de modèle personnalisée, tant que le modèle d'entité correspondant en arrière-plan est construit, il vous suffit de créer deux nouvelles vues personnalisées sur le frontal, et un simple ajout, suppression, modification et recherche peuvent être terminés sans écrire une phrase de code JS.
3. Liaison du composant sélectionné
Ce qui précède introduit la syntaxe de l'addition, de la suppression, de la modification et de la recherche de l'emballage T4. Tous les composants de la page sont essentiellement des zones de texte. Cependant, dans les projets réels, de nombreuses pages de requête et d'édition auront des boîtes déroulantes à afficher. Comment devons-nous gérer la boîte déroulante? Si vous ne gardez pas cela secret, donnez simplement une solution. Par exemple, nous pouvons placer la source de données de la boîte déroulante en arrière-plan dans la page d'édition.
Entité de l'utilisateur
[Datacontract] public class utilisateur {[dataMember] public int id {get; ensemble; } [DataMember] Nom de chaîne publique {get; ensemble; } [DataMember] public String fullName {get; ensemble; } [DataMember] public int Age {get; ensemble; } [DataMember] public String des {get; ensemble; } [DataMember] public DateTime CreateTime {get; ensemble; } [DataMember] public String StrCreateTime {get; ensemble; } [DataMember] public String DepartmentId {get; ensemble; } [DataMember] Départements d'objets publics {get; ensemble; }}Puis modifiez la page
public ActionResult Edit (modèle d'utilisateur) {Model.Departments = DepartmentModel.getData (); Return View (modèle);}Ensuite, liez l'extrémité avant.
<div> <label for = "txt_des"> Department </Bel> <select id = "sel_dept" data-bind = "Options: editmodel.departments, optionStext: 'name', optionsValue: 'id', valeur: editmodel.departmentId"> </lect> </v>
Le code JS n'a pas besoin d'être modifié. Lors de l'ajout ou de l'édition, les champs de département peuvent être automatiquement ajoutés au ViewModel.
Bien sûr, les boîtes déroulantes utilisées par beaucoup de nos projets ne sont pas simplement sélectionnées, car le style de sélection simple est vraiment laid, de sorte que de nombreux composants sélectionnés sont produits, tels que Select2, Multiselect, etc. partagé par le blogueur auparavant. Lorsque vous utilisez ces composants pour initialiser le SELECT, vous constaterez que la boîte déroulante de l'interface n'est plus une balise de sélection simple, mais est composée de nombreuses autres balises personnalisées par le composant. Prenons le composant SELECT2 comme exemple pour voir s'il est possible d'initialiser directement en fonction de ce qui précède.
Nous ajoutons la dernière phrase pour modifier le code JS initialisé par la page:
<script type = "text / javascript"> $ (function () {var model = @ html.raw (newtonsoft.json.jsonconvert.serializeObject (modèle)); var ViewModel = {formid: "Formedit", editModel: model, urls: {soupmed.id == 0? "/ user / add": "/ User / update"}, validator: {fields: {name: {validators: {notempty: {message: 'le nom ne peut pas être vide!Grâce aux ajouts et aux modifications, c'est en effet possible! Analyse de la raison, bien que la page HTML change après l'initialisation du composant SELECT2, le composant présentera éventuellement la valeur sélectionnée sur le contrôle de sélection d'origine. Je ne sais pas si d'autres composants d'initialisation de sélection seront comme ceci sauf SELECT2, et ils attendent d'être vérifiés. Cependant, il y a une chose à expliquer ici. Avant d'initialiser SELECT2, les options dans la boîte déroulante doivent être liées à la valeur, c'est-à-dire que l'initialisation du composant doit être placée après ko.ApplyBinding ().
4. Résumé
À ce stade, KO combiné avec la génération de modèles bootstaptable et l'utilisation de commandes sélectionnées sont essentiellement disponibles, et bien sûr, il doit encore être amélioré. Si vous avez du temps plus tard, le blogueur réglera la combinaison d'autres composants frontaux et KO, comme notre contrôle de date le plus courant. Si vous avez des questions, veuillez me laisser un message et l'éditeur répondra à tout le monde à temps. Merci beaucoup pour votre soutien au site Web Wulin.com!