Prefácio: o artigo anterior apresenta o encapsulamento da adição, exclusão, modificação e pesquisa do KO, o que realmente salva muitos código JS. O blogueiro é uma pessoa que gosta de ser preguiçosa. Ele sempre sente que essas adições básicas, deleções, modificações e verificações podem gerar diretamente efeitos de página por meio de uma ferramenta e nenhum código é necessário. Isso seria tão legal. Então eu estudei a gramática de T4. Embora eu não tenha dominado completamente, tive um entendimento geral. Portanto, o artigo de hoje: gerar rapidamente páginas através de modelos T4.
Artigos da série Knockoutjs:
Bootstraptable e KnockoutJs se combinam para alcançar a função de adicionar, excluir, modificar e verificar [1]
Bootstraptable e KnockoutJs se combinam para alcançar a função de adicionar, excluir, modificar e verificar [2]
Bootstraptable + KnockoutJs combina -se para realizar a solução de adicionar, excluir, modificar e verificar (3) Dois modelos de vista podem completar a adição, excluir, modificar e verificar
1. Introdução ao uso de T4
Sabemos que, ao adicionar visualizações no MVC, o efeito da página de adicionar, excluir, modificar e verificar pode ser gerado automaticamente. Isso ocorre porque o MVC possui modelos básicos internos para adicionar, excluir, modificar e verificar. A sintaxe desses modelos deve usar o T4, então onde estão esses modelos? Depois de procurar artigos relacionados, descobri que a localização do MVC4 e dos modelos de versão abaixo é muito diferente da do MVC5 e acima.
• Localização do modelo para MVC4 e as seguintes versões: VS Instalação Diretório +/ItemTemplates/CSharp/Web/MVC 2/CodeTemplates. Por exemplo, os arquivos d:/programas do blogueiro (x86)/Microsoft Visual Studio 12.0/Common7/IDE/ItemTemplates/csharp/web/mvc 4/codeTemplates.
Encontre o modelo correspondente ao cshtml e existem arquivos TT correspondentes que adicionam, excluem, modificam e verifiquem
• MVC5 e acima do modelo Localização: Dê diretamente a localização do modelo do blogueiro D:/Arquivos de Programas (x86)/Microsoft Visual Studio 12.0/Common7/IDE/Extensions/Microsoft/Web/MVC/Scaffolding/Modelos
Depois de saber disso, o próximo passo é remodelar o modelo e adicionar seu próprio conteúdo gerado. Você pode copiar diretamente a lista e os modelos de edição para a auto-transformação, mas depois de pensar nisso, é melhor não tocar no MVC embutido. Não é melhor construir seus próprios modelos.
Crie uma nova pasta no diretório raiz do projeto da web atual, nomeie -o codeTemplates e copie as duas pastas de modelo MVCControllerEmpty e MVCView no modelo MVC para a pasta CodeTemplates, remova os modelos originais e crie vários novos modelos, como mostrado na figura abaixo:
Dessa forma, quando adicionamos um novo controlador e criamos uma nova visualização, podemos ver nosso modelo personalizado:
2. Introdução ao código T4
O acima introduz como criar seu próprio modelo. Depois que o modelo for construído, você deve começar a preencher o conteúdo correspondente nele. Se a gramática do T4 for expandida, esse artigo será interminável. Jardineiros interessados podem pesquisar no jardim. Ainda existem muitos artigos. Vamos dar uma olhada em alguns conteúdos de modelo aqui. Outra coisa a observar é que parece que, após o MVC5, o sufixo do arquivo de modelo de T4 foi alterado para T4 e os modelos anteriores sempre terminaram com o TT. Sem olhar para as diferenças em sua sintaxe, estima -se que deve haver pouca diferença.
1. Controller.Cs.T4
Por que reescrever este modelo de controlador vazio? O blogueiro pensa que muitos métodos de adicionar, excluir, modificar e verificar precisam ser escritos manualmente e é muitos problemas para escrever um modelo diretamente. Vamos dar uma olhada no código de implementação no modelo:
<#@ modelo linguagem = "c#" hostspecific = "true"#> <#@ output Extension = "cs"#> <#@ parâmetro tipo = "System.string" name = "controlName"#> <#@ parâmetro type = "System.string" name = "controllerrootname"#> <#@ parâmetro = "System.string" name = " name = "Areaname"#> <#var index = controlName.LastIndexof ("controlador"); var modeloName = controlName.substring (0, index);#> usando o sistema; usando o System.Collection.Genic; usando System.linq; usando System.Web; #>: Controlador {public ActionResult index () {return View ();} public ActionResult Edit (< #= ModelName #> Model) {return View (Model);} [httpget] public jsonResult get (int limite, int offset) {return json (new {}}, jsonResult gethavior (int limit.fset) {return {}/}, jsonRequestBerHaviR. JSONRESULT ADD (<#= ModelName#> odata) {<#= ModelName#> model.add (odata); retorna json (new {}, jsonRequestBehavior.allowget);} // Atualizar entidade [httppost] public jsonResult Atualização (#= ModelName#> OdatA) #> Model.update (odata); retorna json (novo {}, jsonRequestBeHavior.allowget);} // excluir entidade [httppost] public jsonResult delete (list << #= modelName #> odata) {< #ModelName #> Model.delete (ometete); JsonRequestBeHavior.Allowget);}}}Este conteúdo não é difícil de entender. Basta verificar o código do controlador gerado:
usando o sistema; usando o System.Collection.Genic; usando o System.Linq; usando o System.web; usando o System.web.mvc; usando testko.models; namespace testko.controllers {public class); JsonResult get (int limit, int offset) {return json (new {}, jsonRequestBehavior.allowget);} // Adicione entidade [httppost] public jsonResult add (user odata) {usermodel.add (odata); Return json (novo {}, jsonRequestBehavior.allowget);} // Atualizar entidade [httppot] public jsonResult update (user odata) {userModel.Update (ODATA); return json (novo {}, jsonRequestBehavior.allowget);} // excluir entidade [httppost] public jsonResult delete (list <suser> odata) {userModel.delete (odata); Return json (novo {}, jsonRequestBehavior.allowget);}}}2. Koindex.cs.t4
Este modelo é usado principalmente para gerar páginas de lista, com o código geral da seguinte maneira:
<#@ modelo linguagem = "c#" hostspecific = "true"#> <#@ output Extension = ". cshtml"#> <#@ incluir file = "importar.include.t4"#> <#// A seguinte cadeia if statement produz o código do arquivo e a marcação para uma visualização parcial, usa uma visualização {<eativeIF, ou um layout. if (islayoutPagesElected) {#>@{viewbag.title = "<#= viewName#>"; <#if (! string.isnullorEmpty (layoutPageFile)) {#> Layout = "<#= LayoutPageFile#"; html> <html> <head> <meta name = "viewPort" content = "width = dispositivo-width"/> <title> < #= viewName #> </title> <link href = "~/content/bootstrap/css/bootstrap.min.css" reln = "Stylesheet"/> <link href = "~/content/bootstrap-table/bootstrap-table.min.css" rel = "Stylesheet"/> <script src = "~/scripts/jQuery-1.9.1.minmin.js"> </script> <script src = "~/contentsp/js/boots/jns/boots/boots/boots/boots/jm/jm/jm/jm/jm/jm/jm/jM/ 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/knockut/knock.js/knock.js/knock.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.JS.JS" src = "~/scripts/extensions/knockout.index.js"> </script> <script src = "~/scripts/extensions/knockout.bootstraptable.js"> </script> <script type = "text/javasscript"> (function () {var viewModel = {lindexiDIDIDIDIDIDIDIDIDIDET: "/<#= ViewDatatyPeshortName#>/get", Pagesize: 2,}, urls: {del: "/<#= viewDatatyPeshortName#>/Delete", edit: "/<# : {}}; ko.bindingViewModel (ViewModel);}); </script> </ad Head> <body> <#pushIndent ("");}#> <div id = "ToolBar"> <botão Data-bind = "Click: addClick" type = ""> <paná-hidden ">" True ">"> type = "Button"> <span Aria-hidden = "true"> </span> modifique </button> <botão data-bind = "clique: deleteclick" type = "button"> <span Aria-hidden = "true"> </span> delete </botão> </div> <tabela bind = "bootstraptable: bootstraptable data-checkbox = "true"> </th> <#iEnumerable <ERROWSMETADATA> Propriedades = ModelMetadata.Properties; foreach (propriedadesMetadata em propriedades) {if (Property.caffold &&! Property.isPrimaryKey &&! GetValueExpression (Propriedade)#> </th> <#}}#> </tr> </thead> </tabela> <#// O código a seguir fecha a tag usada no caso de uma exibição usando uma página de layout e o corpo e as tags html no caso de uma página de visualização regular#> <#) se (! {ClearIndent ();#> </body> </html> <#}#> <#@ incluir file = "ModelMetAdatafunctions.cs.include.t4"#>Adicione um índice de visualização e selecione este modelo
O conteúdo da página obtido
@{Layout = null;} <! Doctype html> <html> <head> <meta name = "viewport" content = "width = dispositivo-width"/> <title> Índice </title> <link href = "~/content/bootstrap/cs/bootstrap.minin.csss" Rel = "Styling =" Stylyshleshesh) href = "~/content/bootstrap-table/bootstrap-table.min.css" rel = "Stylesheet"/> <script src = "~/scripts/jQuery-1.9.1.minmin.js"> </script> <script src = "~/contentsp/js/boots/jns/boots/boots/boots/boots/jm/jm/jm/jm/jm/jm/jm/jM/ 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/knockut/knock.js/knock.js/knock.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.bootstraptable.js"></script><script type="text/javascript">$(function () {var viewModel = {bindId: "div_index",tableParams :{url : "/User/Get",pageSize : 2,},urls :{del : "/User/Delete",edit : "/User/Edit",add : "/User/Edit",},queryCondition :{}};ko.bindingViewModel(viewModel);});</script></head><body><div id="toolbar"><button data-bind="click:addClick" type="button"><span aria-hidden="true"></span>Add</button><button Data-Bind = "Clique: EditClick" type = "Button"> <span Aria-hidden = "true"> </span> modifique </button> <botão data-bind = "clique: deleteclick" type = "button"> <span the-hidden = "true"> </span> DeLete </button> </divi- bind = "boots" e "> </span> deLete </button> </divi- bind =" boots ">"> </span> <//button> </Div "<tumtle-hidden =" True "> </span> data-checkbox = "true"> </th> <th data-field = "name"> name </th> <th data-field = "fullname"> fullname </th> <th data-field = "idade"> idade </th> <th data-field = "des" des </s </th data-field = "createTime"> createTime </th Thy </ Data-field = "strCreateTime"> strCreateTimeMudamos o ViewModel mencionado no artigo anterior para a página, para que não precisemos passar do controlador sempre. Altere o nome da coluna da tabela ligeiramente e a página pode ser executada.
Aqui estão alguns pontos a serem otimizados:
(1) As condições de consulta não foram geradas. Se você estudar a sintaxe do T4 um pouco mais profundo, poderá adicionar características aos campos que precisam ser consultados para identificar quais campos precisam ser consultados e, em seguida, gerar automaticamente as condições de consulta correspondentes.
(2) Os nomes das colunas da tabela parecem ser gerados através das propriedades de campo do atributo. Isso é semelhante ao primeiro ponto e ambos precisam estudar a gramática de T4.
3. Koedit.cs.t4
A página do terceiro modelo é o modelo editado e seu código aproximado é o seguinte:
<#@ modelo linguagem = "c#" hostspecific = "true"#> <#@ output Extension = ". cshtml"#> <#@ incluir file = "importar.include.t4"#>@ modelo <#/ viewDatatyPeName#> <#// "form --Control" o atributo é suportado apenas para all editor/ Já de seleção, que usa uma div em bootstrapstring booltype = "system.boolean"; versão requerirmvcversion = nova versão ("5.1.0.0"); bool isControlHtmlattribessupPortEd = mvcversion> = requercversion; Exibir.if (isPartialView regular) {#> <#} else if (islayoutPagesElected) {#>@{viewbag.title = "<#= viewName#>"; <#if (! string.isnullorEmpty (layoutPageFile)) {#> Layout = "<=) ViewName#></h2><#} else {#>@{Layout = null;}<!DOCTYPE html><html><head><meta name="viewport" content="width=device-width" /><title><#= ViewName #></title></head><body><#PushIndent(");}#><#if (ReferenceScriptLibraries) {#> <#if (! islayoutPagesElected && isbundleConfigpresent) {#>@scripts.render ("~/bundles/jQuery")@scripts.render ("~/bundles/jQueryVal") <#} <#mais se (! src = "~/scripts/jQuery-<#= jQueryVersion#>. id = "formedit">@html.hiddenfor (modelo =>> Propriedades <div> <#iEnumerable <ERROPRESÍNICASMETADATA> Propriedades = ModelMetadata.Properties; forEach (PropertyMetadata Propriedade em Propriedades) {if (Property.Scaffold &&! {#> <div> @html.labelFor (modelo => modelo. "Form-Control", data_bind = "valor: editModel. aria-hidden = "true"> </span> salvar </butut> </div> </form> <#var index = viewDatatypeName.LastIndexof ("."); var modelName = viewDatatypeName.Substring (index+1, viewDatatypeName.Length-index-1)#> <script src = "~/scripts/extensions/knockout.edit.js"> </script> <script type = "text/javascript"> $ (function () {var modelo = @html.raw (newtonsoft.json.jsonConvert.SerializeBject (Model); var vista : {submit: model.id == 0? }); </script> <#if (islayoutPagesElected && ReferencesCriptLibraries && isbundleConfigPresent) {#>@seção scripts {@scripts.render ("~/bundpages/jQueryVal")} <#}#> <#se if (islayoutPagesLeted & src = "~/scripts/jQuery-< #= jQueryVersion #>. src = "~/scripts/jQuery.validate.unobtrusive.min.js"> </script> <#}#> <#// O código a seguir fecha a tag usada no caso de uma visualização usando uma página de layout e o corpo e as tags html no caso de uma página de visualização regular#> <#se (! {ClearIndent ();#> </body> </html> <#}#> <#@ incluir file = "ModelMetAdatafunctions.cs.include.t4"#>Código gerado:
@model testko.models.user <form od = "formedit">@html.hiddingfor (model => model.id) <div> <div>@html.labelfor (model => model.name, "name", new {@class = "control-label col-xs-2">) @class = "form-control", data_bind = "value: editmodel.name"}) </div> </div> <div> @html.labelfor (model => @Class = "Form-Conntrol", data_bind = "Valor: editmodel.fullName"}) </div> </div> <div> @html.labelfor (model => model.age, "Age", new {@class = "control-label col-xs-2"}) <dd ", @html. "Form-Control", data_bind = "Valor: editmodel.age"}) </div> </div> <div> @html.labelfor (modelo => model.des, "des", new {@class = "control-label col-x-2"}) <div> @html.textbox = "Form-Control", data_bind = "valor: editmodel.des"}) </div> </div> <div> @html.labelfor (model => model.createTime, "createTime", new {@class = "control-label col-xs-2"}) <div> @html. (@class = "control-label col-xs-2"}) <dd> @html. "Form-Control", data_bind = "Valor: editModel.CreateTime"}) </div> </div> <div>@html.labelfor (modelo => model.strCreateTime, "strcreateTime", new {@class = "control-label col-xS-2"}) <> htrCeartime "@cllass =" control-label col-xS-2 "}) <> {@Class = "Form-Control", data_bind = "Valor: editmodel.strcreateTime"}) </div> </div> <div> <button type = "button" data-Dismiss = "modal"> <span ARIA-Hidden = "True"> </span> Close </lobt> <butt type = "> subida"> <panle-hidden = "true"> </span> </lobt> <butt) aria-hidden="true"></span>Save</button></div></form><script src="~/Scripts/extensions/knockout.edit.js"></script><script type="text/javascript">$(function () {var model = @Html.Raw(Newtonsoft.Json.JsonConvert.SerializeObject(Model));var ViewModel = {formid: "formedit", editModel: Model, URLs: {submit: model.id == 0? "/Usuário/Adicionar": "/Usuário/Update"}, Validator: {FIELDS: {Nome: {Validadores: {NotEmpty: {Message: 'O nome não pode ser! '}}}}}}}; ko.bindingeditViewModel (ViewModel);Obviamente, o código também precisa ser ligeiramente modificado. Ao adicionar uma página de modelo personalizada, desde que o modelo de entidade correspondente seja construído em segundo plano, você só precisará criar duas novas visualizações personalizadas no front end e uma adição, exclusão, modificação e pesquisa simples podem ser concluídas sem escrever uma frase de código JS.
3. Ligação do componente selecionado
O acima introduz a sintaxe da adição de embalagem T4, exclusão, modificação e pesquisa. Todos os componentes da página são basicamente caixas de texto. No entanto, em projetos reais, muitas páginas de consulta e edição terão caixas suspensas para exibir. Como devemos lidar com a caixa suspensa? Se você não mantiver em segredo, basta dar uma solução. Por exemplo, podemos colocar a fonte de dados da caixa suspensa em segundo plano na página de edição.
Entidade do usuário
[DATAContract] public class Usuário {[Datamember] public int id {get; definir; } [DataMember] Nome da string pública {get; definir; } [DataMember] Public String fullName {get; definir; } [DataMember] Public Int Age {get; definir; } [DataMember] Public String des {get; definir; } [DataMember] Public DateTime CreateTime {get; definir; } [DataMember] Public String strCreateTime {get; definir; } [DataMember] Public String DepartmentId {get; definir; } [DataMember] departamentos de objetos públicos {get; definir; }}Em seguida, edite a página
public ActionResult Edit (Modelo do Usuário) {Model.Departments = DepartmentModel.getData (); Return View (Model);}Em seguida, prenda a extremidade frontal.
<div> <gravadora para = "txt_des"> departamento </abely> <select id = "Sel_dept" data-bind = "Opções: editmodel.departments, optionStExt: 'name', optionsValue: 'Id', valor: editmodel.departmentid"> </select> </div>
O código JS não precisa ser modificado. Ao adicionar ou editar, os campos de departamento podem ser adicionados automaticamente ao ViewModel.
Obviamente, as caixas suspensas usadas por muitos de nossos projetos não são simplesmente selecionadas, porque o estilo de seleção simples é realmente feio, muitos componentes selecionados são produzidos, como select2, multisselect etc. compartilhados pelo blogueiro antes. Ao usar esses componentes para inicializar a seleção, você descobrirá que a caixa suspensa na interface não é mais uma tag de seleção simples, mas é composta por muitas outras tags personalizadas pelo componente. Vamos tomar o componente SELECT2 como exemplo para ver se é viável inicializar diretamente de acordo com o acima.
Adicionamos a última frase para editar o código JS inicializado pela página:
<script type = "text/javascript"> $ (function () {var modelo = @html.raw (newtonsoft.json.jsonConvert.SerializeObject (Model)); var ViewModel = {formid: "formedit", editModel: Model, Urls: {Submit: Model.id: "/Usuário/atualização"}, validador: {campos: {nome: {validadores: {Notimpty: {message: 'O nome não pode ser vazio!Através das adições e edições, isso é realmente viável! Análise do motivo, embora a página HTML altere após a inicialização do componente Select2, o componente eventualmente apresentará o valor selecionado no controle de seleção original. Não sei se outros componentes de inicialização selecionados serão assim, exceto o Select2, e eles estão esperando para serem verificados. No entanto, há uma coisa a ser explicada aqui. Antes de inicializar o Select2, as opções na caixa suspensa devem estar vinculadas ao valor, ou seja, a inicialização do componente deve ser colocada após o ko.applyBinding ().
4. Resumo
Nesse ponto, o KO combinado com a geração de modelos inicializáveis e o uso de controles selecionados estão basicamente disponíveis e, é claro, ele ainda precisa ser melhorado. Se você tiver tempo depois, o blogueiro resolverá a combinação de outros componentes do front-end e KO, como o nosso controle de data mais comum. Se você tiver alguma dúvida, deixe -me uma mensagem e o editor responderá a todos a tempo. Muito obrigado pelo seu apoio ao site wulin.com!