Prefacio: El artículo anterior presenta la encapsulación de la adición de KO, la eliminación, la modificación y la búsqueda, lo que de hecho guarda mucho código JS. El blogger es una persona a la que le gusta ser perezoso. Siempre siente que estas adiciones, deleciones, modificaciones y verificaciones básicas pueden generar directamente los efectos de la página a través de una herramienta, y no se necesita ningún código. Eso sería tan genial. Entonces estudié la gramática de T4. Aunque no lo dominaba por completo, tenía un entendimiento general. Entonces, el artículo de hoy: genere rápidamente páginas a través de plantillas T4.
Artículos de la serie KnockoutJS:
BootStraptable y KnockoutJs se combinan para lograr la función de agregar, eliminar, modificar y verificar [1]
BootStraptable y KnockoutJs se combinan para lograr la función de agregar, eliminar, modificar y verificar [2]
BootStraptable + knockoutJS se combina para realizar la solución de agregar, eliminar, modificar y verificar (3) dos modelos de vista pueden completar la adición, eliminar, modificar y verificar
1. Introducción al uso de T4
Sabemos que al agregar vistas en MVC, el efecto de la página de agregar, eliminar, modificar y verificar se puede generar automáticamente. Esto se debe a que MVC tiene plantillas básicas incorporadas para agregar, eliminar, modificar y verificar. La sintaxis de estas plantillas es usar T4, entonces, ¿dónde están estas plantillas? Después de buscar artículos relacionados, descubrí que la ubicación de las plantillas de versión MVC4 y debajo es muy diferente de la de MVC5 y superior.
• Ubicación de la plantilla para MVC4 y las siguientes versiones: VS Directorio de instalación +/itemTemplates/csharp/web/mvc 2/Codetemplates. Por ejemplo, los archivos D:/Programa del blogger (x86)/Microsoft Visual Studio 12.0/Common7/IDE/itemTemplates/Csharp/Web/MVC 4/CodetEmplates.
Encuentre la plantilla correspondiente a CSHTML, y hay archivos TT correspondientes que agregan, eliminan, modifican y verifican
• MVC5 y arriba Ubicación de la plantilla: Dé directamente la ubicación de la plantilla del blogger d:/archivos de programa (x86)/Microsoft Visual Studio 12.0/Common7/IDE/Extensions/Microsoft/Web/MVC/andamiaje/plantillas
Una vez que sepa esto, el siguiente paso es remodelar la plantilla y agregar su propio contenido generado. Puede copiar directamente la lista y editar plantillas a la auto-transformación, pero después de pensarlo, es mejor no tocar el MVC incorporado. No es mejor construir sus propias plantillas usted mismo.
Cree una nueva carpeta en el directorio raíz del proyecto web actual, nombre que CodeTePples y luego copie las dos carpetas de plantilla MVCControllerempty y MVCView en la plantilla MVC a la carpeta de plantillas de códigos, elimine las plantillas originales dentro de él, y luego cree varias plantillas nuevas, como se muestra en la figura a continuación::
De esta manera, cuando agregamos un nuevo controlador y creamos una nueva vista, podemos ver nuestra plantilla personalizada:
2. Introducción del código T4
Lo anterior presenta cómo crear su propia plantilla. Después de construir la plantilla, debe comenzar a rellenar el contenido correspondiente en ella. Si la gramática de T4 se expande, ese artículo será interminable. Los jardineros interesados pueden buscar en el jardín. Todavía hay bastante artículos. Echemos un vistazo a algunos contenidos de plantilla aquí. Otra cosa a tener en cuenta es que parece que después de MVC5, el sufijo de archivo de plantilla de T4 se ha cambiado a T4, y las plantillas anteriores siempre han terminado con TT. Sin mirar las diferencias en su sintaxis, se estima que debería haber poca diferencia.
1. Controlador.cs.t4
¿Por qué reescribir esta plantilla de controlador vacío? El blogger cree que muchos métodos para agregar, eliminar, modificar y verificar deben escribirse manualmente y es muchos problemas escribir una plantilla directamente. Echemos un vistazo al código de implementación en la plantilla:
<#@@ Template Language = "C#" hostspecific = "true"#> <#@ output outple name = "areaname"#> <#var index = controllername.lastIndexOf ("controlador"); var modelname = controlname.substring (0, index);#> usando system.collections.generic; usando system.linq; usando system.web; usando system.web.mvc; usando testko.models; namespace <#= namespace#>#>#> {#>#># : Controlador {public ActionResult index () {return View ();} public ActionResult Edit (< #= ModelName #> Model) {return View (Model);} [httpget] public jsonResult get (int limit, int offset) {return json (new {}, jSonRequestbebhavior.allawetget);} // add [hattTpost] Add (< #= ModelName #> Odata) {< #= ModelName #> Model.add (Odata); return json (new {}, jsonRequestBehavior.Allowget);} // actualizar entidad [httppost] public jsonResult Update (< #= modelname #> odata) {< #= modelname #> }, JsonRequestBehavior.Allowget);} // Eliminar entidad [httppost] public jsonResult delete (list << #= modelName #> odata) {< #= modelName #> model.delete (odata); return json (nuevo {}, jsonRequestbehavior.allowget);}}}}}Este contenido no es difícil de entender. Simplemente verifique el código del controlador generado:
utilizando System; usando System.Collections.Generic; Usando System.Linq; usando System.Web; Usando System.Web.MVC; Uso de testKo.Models; Namespace testko.controllers {public class UserController: Controller {public ActionResult Index () {View de retorno ();} Public ActionResult Edit (Modelo de usuario) {View de retorno (Modelo);} JsonResult get (int limit, int offset) {return json (new {}, jsonRequestBehavior.Allowget);} // Agregar entidad [httppost] public jsonResult add (usuario odata) {usermodel.add (odata); return json (new {}, jsonRequestBehavior.Anlowget);} // Actualizar entidad [httpPost] public jsonResult Update (usuario odata) {usermodel.update (odata); return json (new {}, jsonRequestBehavior.Anlowget);} // Eliminar entidad [httppost] public jsonResult delete (list <serem> odata) {usermodel.delete (odata); return json (new {}, jsonRequestBehavior.Anlowget);}}}2. Koindex.cs.t4
Esta plantilla se usa principalmente para generar páginas de lista, con el código general de la siguiente manera:
<#@@ template lenguaje = "c#" hostspecific = "true"#> <#@ output outputs extension = ". cshtml"#> <#@@@@@@#> <#// La siguiente opción if-statement sale el código de encabezado de archivo y el marcado para una vista parcial, una vista usando una página de diseño o una página regular. If (espartialview). if (islayoOutPageSelected) {#>@{ViewBag.title = " html> <html> <fead> <meta name = "viewport" content = "width = dispositivo-width"/> <title> < #= viewName #> </title> <link href = "~/content/bootstrap/css/bootstrap.min.css" Rel = "Stylesheet"/> <Link href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" /><script src="~/scripts/jquery-1.9.1.min.js"></script><script src="~/Content/bootstrap/js/bootstrap.min.js"></script><script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script><script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script><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"> </script> <script src = "~/scripts/extensions/knockout.index.js"> </script> <script> <script. src = "~/scripts/extensions/knockout.index.js"> </script> <script src = "~/scripts/extensions/knockout.bootstaptable.js"> </script> <script type = "text/javaScript"> $ (function () {var viewModel = {bindId: "div_index", tableparams: {url: {url: "/<<#= ViewDatatyPeshortName#>/get", PageSize: 2,}, URLS: {del: "/<#= ViewDatAtyPeshortName#>/delete", editar: "/<#= ViewDatAtyPeshortName#>/editar", agregar: "/<#= ViewDatatyPeshortName#>/edit",}, querycondation. : {}}; ko.bindingviewModel (viewModel);}); </script> </head> <body> <#pushindent ("");}#> <div id = "Barbar"> <button data-bind = "click: addCkick" type = "botón"> <span aria-hidden = "verdadero"> </span> agregado </botón <button <button de botón: button = " type = "Button"> <span aria-hidden = "true"> </span> modificar </botón> <botón data-bind = "haga clic: DeleteClick" type = "botón"> <span aria-hidden = "true"> </span> delete </botón> </div> <table data-bind = "bootStaptable: bootStraptable"> <tr> data-checkbox = "true"> </th> <#ienumerable <propertyMetadata> Properties = modelMetadata.Properties; foreach (propiedad de propiedades de propiedad en propiedades) {if (Property.ScAffold &&! Property.IsPrimaryKey &&! Property.ISforeignKey) GetValueExPression (propiedad)#> </th> <#}}#> </tr> </thead> </table> <#// El siguiente código cierra la etiqueta utilizada en el caso de una vista utilizando una página de diseño y las etiquetas HTML en el caso de una página de vista) {ClearIndent ();#> </body> </html> <#}#> <#@@ include file = "modelmetadatafunctions.cs.include.t4"#>Agregue un índice de vista y seleccione esta plantilla
El contenido de la página obtenido
@{Layout = null;} <! DocType html> <html> <head> <meta name = "viewport" content = "width = dispositivo-width"/> <title> índice </title> <link href = "~/content/bootstrap/css/bootstrap.min.css" Rel = "Stylesheet"/> <Linket <> <Link Linke href="~/Content/bootstrap-table/bootstrap-table.min.css" rel="stylesheet" /><script src="~/scripts/jquery-1.9.1.min.js"></script><script src="~/Content/bootstrap/js/bootstrap.min.js"></script><script src="~/Content/bootstrap-table/bootstrap-table.min.js"></script><script src="~/Content/bootstrap-table/locale/bootstrap-table-zh-CN.js"></script><script src="~/scripts/knockout/knockout-3.4.0.min.js"></script><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"> </script> <script> <script> src = "~/scripts/extensions/knockout.bootstaptable.js"> </script> <script type = "text/javaScript"> $ (function () {var viewModel = {bindId: "div_index", tableParams: {url: "/user/get", pageSize: 2,}, urls: {del:: "/user. "/User/edit", add: "/user/edit",}, QueryCondition: {}}; ko.bindingviewModel (ViewModel);}); </script> </body> <body> <dividi = "Toolbar"> <Button-bind = "Click: addClick" type = "Booth"> <span aria-hidden "verdadero" data-bind = "haga clic: editClick" type = "botón"> <span aria-hidden = "true"> </span> modificar </boton> <botón data-bind = "haga clic: DeleteClick" type = "Button"> <span aria-hidden = "true"> </span> delete </botón> </div> <tabla data-bind = "bootstraptable: bootstraptable data-checkbox = "true"> </th> <th data-field = "name"> name </th> <th data-field = "fullname"> fullname </th> <th data-field = "edad"> edad </th> <th data-field = "des"> des </th> <th data-field = "createTime"> creatime </th> Data-Field = "StrCreateTime"> StrCreateTime </th> </tr> </thead> </table> </body> </html> index.cshtmlMovimos el ViewModel mencionado en el artículo anterior a la página, para que no tengamos que pasarlo del controlador cada vez. Cambie ligeramente el nombre de la columna de la tabla y la página puede ejecutarse.
Aquí hay algunos puntos para optimizar:
(1) Las condiciones de consulta no se han generado. Si estudia la sintaxis de T4 un poco más profunda, puede agregar características a los campos que deben consultar para identificar qué campos deben consultar y luego generar automáticamente las condiciones de consulta correspondientes.
(2) Los nombres de la columna de la tabla parecen generarse a través de las propiedades de campo del atributo. Esto es similar al primer punto, y ambos necesitan estudiar la gramática de T4.
3. Koedit.cs.t4
La tercera página de plantilla es la plantilla editada, y su código aproximado es el siguiente:
<#@ template language="C#" HostSpecific="True" #><#@ output extension=".cshtml" #><#@ include file="Imports.include.t4" #>@model <#= ViewDataTypeName #><#// "form-control" attribute is only supported for all EditorFor() in System.Web.Mvc 5.1.0.0 or later versions, except for casilla de verificación, que utiliza un div en bootstraPtring booltype = "System.Boolean"; Versión requeridamvcversion = nueva versión ("5.1.0.0"); bool IsControlhtmlatTributessUpported = mvCversion> = requerido View Regular.if (isPartialView) {#> <#} else if (isLayoutPageSelected) {#>@{ViewBag.title = "<#= ViewName#>"; <#! String.isNullorEmpty (LayOutPageFile) {#> Layout = "<#= = = = = LECHEPAFILE#>"; <#}#>}#>} ViewName#> </h2> <#} else {#>@{Layout = null;} <! DocType html> <html> <fead> <meta name = "viewport" content = "width = dispositivo-width"/> <title> <#= ViewName#> </bitle> </HEAD> <Body> <#pushind (");}#> <##(##(##(#(##(##(##if (reference (#if (reference) {#> <#if (! isLayoutPageSelected && isbundleconfigPresent) {#>@scripts.render ("~/bundles/jQuery")@scripts.render ("~/bundles/jqueryVal") <#}#> <#else if (! IslayPagesElected) {#> <script src = "~/" ~/"script" JqueryVersion#>. Min.js "> </script> <script src =" ~/scripts/jquery.validate.min.js "> </script> <script src =" ~/scripts/jquery.validate.unobtrusive.min.js "> </script> <#}#> <formul model.Id)<div><#IEnumerable<PropertyMetadata> properties = ModelMetadata.Properties;foreach (PropertyMetadata property in properties) {if (property.Scaffold && !property.IsPrimaryKey && !property.IsForeignKey) {#><div>@Html.LabelFor(model => model.<#= GetValueExpression(property) #>, "<#= GetValueExPression (propiedad)#>", nuevo {@class = "Control-Label Col-xs-2"}) <div> @html.textboxfor (model => modelo. <#= GetValueExPression (propiedad)#>, nuevo {@class = "form-contRol", data_bind = "valor: editmodel. <#= =#=#>, Nuevo {@class =" Form-Control ", data_bind =" Value: EditModel. <#=#= #> "}) </div> </div> <#}}#> </div> <div> <button type =" botón "data-dismiss =" modal "> <span aria-hidden =" true "> </span> cero </boton> <button type =" shipt "> <span aria-hidden =" true "> </span> save </boton> </divis> </formy <#######Var ViewDatatyPename.lastIndexof ("."); Var modeleName = ViewDatyPenameName.Substring (index+1, ViewDatatyPename.length-Index-1);#> <script src = "~/scripts/extensions/knockout.edit.js"> </script> <script type = "text/javascript"> $ (function () {) {) {) {VAR MODELL. @Html.raw (newtonsoft.json.jsonconvert.serializeObject (modelo)); var viewModel = {formid: "formedit", editModel: model, urls: {Subt: Model.id == 0? {Validadores: {NotEmty: {Mensaje: 'El nombre no puede estar vacío!'}}}}}}}}; ko.bindingeditviewModel (ViewModel); {@Scripts.render ("~/bundles/jqueryVal")} <#}#> <#if (isLayoutPageSelected && referencescriptLibraries) {#> <script src = "~/scripts/jQuery-<#= jQueryVersion#>. Min.js"> </script> <script src = "~/scripts/jquery.validate.min.js"> </script> <script src = "~/scripts/jQuery.validate.unobtrusive.min.js"> </script> <script src = "~/scripts/jQuery.validate.unobtrusive.min.js"> </script> <##> <#> </////Code. Utilizado en el caso de una vista utilizando una página de diseño y las etiquetas de cuerpo y HTML en el caso de una página de vista regular#> <#if (! isPartialView &&! isLayoutPageselected) {clearindent ();#> </body> </html> <#}#> <#@ include file = "modelmetAtafunctions.cs.include.t4"#>#>#>Código generado:
@model testko.models.user <form id = "formedit">@html.hiddenfor (model => model.id) <div> <div>@html.labelfor (model => model.name, "nombre", nuevo {@class = "control-etiqueta col-xs-2"}) <div>@html.textbor (modelo (model Model, model. @class = "form-confontrol", data_bind = "valor: editModel.name"}) </div> </div> <div> @html.labelfor (model => model.fullName, "fullName", nuevo {@class = "control-label col-xs-2"}) <div> @html.textboxfor (modelo => model de control.label. @class = "form-confontrol", data_bind = "valor: editModel.fullName"}) </div> </div> <div> @html.labelfor (model => model.age, "edad", nuevo {@class = "control-label col-xs-2"}) <div> @html.textboxfor (modelo => modelo = >. "Form-Control", data_bind = "valor: editModel.age"}) </div> </div> <div> @html.labelfor (model => model.des, "des", new {@class = "control-Label col-xs-2"}) <div> @html.TextBoxFor (model => model.des, new, @clas data_bind = "valor: editModel.des"}) </div> </div> <div> @html.labelfor (model => model.createTime, "createTeTime", new {@class = "control-label col-xs-2"}) <div> @html.textboxfor (model => model.createTime, new {@class = "," cclass = ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",", ",". data_bind = "valor: editModel.CreateTime"}) </div> </div> <div> @html.labelfor (model => model.strcreatetime, "strcreatetime", nuevo {@class = "control-label col-xs-2"}) <iv> @html.textboxfor (modelo => model.strcreatEtime, nuevo, nuevo, nauce. "" Form-Control ", data_bind =" Valor: editModel.strcreateTime "}) </div> </div> <div> <button type =" botón "data-dismiss =" modal "> <span aria-hidden =" true "> </span> cerrer </botte> <button type =" enviar "> <span aria-hidden = "true"> </span> save </boton> </div> </orm> <script src = "~/scripts/extensions/knockout.edit.js"> </script> <script type = "text/javaScript"> $ (function () {var model = @html.raw (newtononsoft.json.jsonconvert.serialize); = {formid: "formedit", editModel: model, urls: {Subt: Model.id == 0? '}}}}}}}; ko.bindingeditViewModel (ViewModel);Por supuesto, el código también debe modificarse ligeramente. Al agregar una página de plantilla personalizada, siempre que se construya el modelo de entidad correspondiente en el fondo, solo necesita crear dos nuevas vistas personalizadas en la parte delantera, y una simple adición, eliminación, modificación y búsqueda se pueden completar sin escribir una oración de código JS.
3. ANUNCIO DEL COMPONENTE SELECCIONADO
Lo anterior presenta la sintaxis de la adición de empaque T4, deleción, modificación y búsqueda. Todos los componentes de la página son básicamente cuadros de texto. Sin embargo, en proyectos reales, muchas páginas de consulta y edición tendrán cuadros desplegables para mostrar. ¿Cómo debemos lidiar con el cuadro desplegable? Si no lo mantiene en secreto, solo da una solución. Por ejemplo, podemos colocar la fuente de datos del cuadro desplegable en el fondo en la página de edición.
Entidad del usuario
[DataContract] Public Class User {[DataMember] public int id {get; colocar; } [DataMember] Nombre de cadena pública {get; colocar; } [DataMember] public String FullName {get; colocar; } [DataMember] public int Age {get; colocar; } [DataMember] Public String des {get; colocar; } [DataMember] Public DateTime CreateTime {get; colocar; } [DataMember] public String strCreateTime {get; colocar; } [DataMember] Public String Departmid {get; colocar; } [DataMember] departamentos de objetos públicos {get; colocar; }}Luego edite la página
Public ActionResult Edit (Modelo de usuario) {Model.departments = DepartmentModel.getData (); View de retorno (modelo);}Luego ata el extremo frontal.
<Div> <etiqueta for = "txt_des"> Departamento </etiqueta> <select id = "sel_dept" data-bind = "Option
El código JS no necesita ser modificado. Al agregar o editar, los campos de departamento se pueden agregar automáticamente al Modelo View.
Por supuesto, los cuadros desplegables utilizados por muchos de nuestros proyectos no son simplemente seleccionados, porque el estilo selecto simple es realmente feo, por lo que se producen muchos componentes seleccionados, como SELECT2, Multiselect, etc. compartido por el blogger antes. Al usar estos componentes para inicializar la selección, encontrará que el cuadro desplegable en la interfaz ya no es una etiqueta Select Select, sino que está compuesta por muchas otras etiquetas personalizadas por el componente. Tomemos el componente Select2 como un ejemplo para ver si es factible inicializarse directamente de acuerdo con lo anterior.
Agregamos la última oración para editar el código JS inicializado por la página:
<script type = "text/javaScript"> $ (function () {var model = @html.raw (newtonsoft.json.jsonconvert.serializeObject (modelo)); var vermodel = {formid: "formedit", editModel: model, urls: {someter: model.id == 0? "" "/User/update"}, Validator: {Fields: {name: {Validators: {noTempty: {Mensaje: 'El nombre no puede estar vacío!A través de las adiciones y ediciones, ¡esto es realmente factible! Análisis de la razón, aunque la página HTML cambia después de inicializar el componente SELECT2, el componente eventualmente presentará el valor seleccionado en el control de selección original. No sé si otros componentes de inicialización seleccionados serán así, excepto Select2, y están esperando ser verificados. Sin embargo, hay una cosa que explicar aquí. Antes de inicializar SELECT2, las opciones en el cuadro desplegable deben estar unidos al valor, es decir, la inicialización del componente debe colocarse después de ko.applyBinDing ().
4. Resumen
En este punto, KO combinado con la generación de plantillas bootstraptable y el uso de controles seleccionados están básicamente disponibles y, por supuesto, aún debe mejorarse. Si tiene tiempo más tarde, el blogger resolverá la combinación de otros componentes frontales y KO, como nuestro control de fecha más común. Si tiene alguna pregunta, déjame un mensaje y el editor responderá a todos a tiempo. ¡Muchas gracias por su apoyo al sitio web de Wulin.com!