隐藏

ASP.NET MVC使用jQuery Template实现批量更新

发布:2023/2/5 17:09:02作者:管理员 来源:本站 浏览次数:627

这篇文章介绍了ASP.NET MVC使用jQuery Template实现批量更新的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

思路


   引用jQuery Template所需要的js文件:jquery.tmpl.min.js

   在<script type="text/x-jquery-tmpl" id="movieTemplate"></script>中生成模版内容,里面包含占位符

   点击添加按钮的时候,把模版内容追加到界面上,并给占位符赋值


jQuery Template的内容大致是这样:



<script type="text/x-jquery-tmpl" id="movieTemplate">

<li style="padding-bottom:15px">

 

   <input autocomplete="off" name="FavouriteMovies.Index" type="hidden" value="${index}" />

 

   <img src="/Content/images/draggable-icon.png" style="cursor: move" alt=""/>

 

   <label>Title</label>

   <input name="FavouriteMovies[${index}].Title" type="text" value="" />

 

   <label>Rating</label>

   <input name="FavouriteMovies[${index}].Rating" type="text" value="0" />

 

   <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  onclick="$(this).parent().remove();">Delete</a>

</li>

</script>


为了得到以上内容,由帮助类方法获得:



<script type="text/x-jquery-tmpl" id="movieTemplate">

       @Html.CollectionItemJQueryTemplate("MovieEntryEditor", new Movie())

</script>

帮助类CollectionEditingHtmlExtensions:


模版内容同样是通过MovieEntryEditor.cshtml这个部分视图生成的,只不过生成的内容中包含了占位符。




using System;

using System.Collections.Generic;

using System.Web;

using System.Web.Mvc;

using System.Web.Mvc.Html;

 

namespace VariableCollection.Extension

{

   public static class CollectionEditingHtmlExtensions

   {

       /// <summary>

       /// 目标是生成如下格式

       ///<input autocomplete="off" name="FavouriteMovies.Index" type="hidden" value="6d85a95b-1dee-4175-bfae-73fad6a3763b" />

       ///<label>Title</label>

       ///<input class="text-box single-line" name="FavouriteMovies[6d85a95b-1dee-4175-bfae-73fad6a3763b].Title" type="text" value="Movie 1" />

       ///<span class="field-validation-valid"></span>

       /// </summary>

       /// <typeparam name="TModel"></typeparam>

       /// <param name="html"></param>

       /// <param name="collectionName">集合属性的名称</param>

       /// <returns></returns>

       public static IDisposable BeginCollectionItem<TModel>(this HtmlHelper<TModel> html, string collectionName)

       {

           if (string.IsNullOrEmpty(collectionName))

           {

               throw new ArgumentException("collectionName is null or empty","collectionName");

           }

           string collectionIndexFieldName = String.Format("{0}.Index", collectionName);//FavouriteMovies.Index

           string itemIndex = null;

           if (html.ViewData.ContainsKey(JQueryTemplatingEnabledKey))

           {

               itemIndex = "${index}";

           }

           else

           {

               itemIndex = GetCollectionItemIndex(collectionIndexFieldName);

           }

 

           //比如,FavouriteMovies[6d85a95b-1dee-4175-bfae-73fad6a3763b]

           string collectionItemName = string.Format("{0}[{1}]", collectionName, itemIndex);

 

           TagBuilder indexField = new TagBuilder("input");

           indexField.MergeAttributes(new Dictionary<string, string>() {

               { "name", String.Format("{0}.Index", collectionName) }, //name="FavouriteMovies.Index"

               { "value", itemIndex },//value="6d85a95b-1dee-4175-bfae-73fad6a3763b"

               { "type", "hidden" },

               { "autocomplete", "off" }

           });

           html.ViewContext.Writer.WriteLine(indexField.ToString(TagRenderMode.SelfClosing));

 

           return new CollectionItemNamePrefixScope(html.ViewData.TemplateInfo, collectionItemName);

       }

 

        private class CollectionItemNamePrefixScope : IDisposable

        {

            private readonly TemplateInfo _templateInfo;

            private readonly string _previousPrefix;

 

            public CollectionItemNamePrefixScope(TemplateInfo templateInfo, string collectionItemName)

            {

                this._templateInfo = templateInfo;

                _previousPrefix = templateInfo.HtmlFieldPrefix;

                templateInfo.HtmlFieldPrefix = collectionItemName;

            }

 

            public void Dispose()

            {

                _templateInfo.HtmlFieldPrefix = _previousPrefix;

            }

        }

 

       /// <summary>

       /// 以FavouriteMovies.Index为键,把Guid字符串存放在上下文中

       /// 如果是添加进入部分视图,就直接生成一个Guid字符串

       /// 如果是更新,为了保持和ModelState的一致,就遍历原先的Guid

       /// </summary>

       /// <param name="collectionIndexFieldName">FavouriteMovies.Index</param>

       /// <returns>返回Guid字符串</returns>

       private static string GetCollectionItemIndex(string collectionIndexFieldName)

       {

           Queue<string> previousIndices = (Queue<string>)HttpContext.Current.Items[collectionIndexFieldName];

           if (previousIndices == null)

           {

               HttpContext.Current.Items[collectionIndexFieldName] = previousIndices = new Queue<string>();

               string previousIndicesValues = HttpContext.Current.Request[collectionIndexFieldName];

               if (!string.IsNullOrWhiteSpace(previousIndicesValues))

               {

                   foreach (string index in previousIndicesValues.Split(','))

                   {

                       previousIndices.Enqueue(index);

                   }

               }

           }

           return previousIndices.Count > 0 ? previousIndices.Dequeue() : Guid.NewGuid().ToString();

       }

 

       private const string JQueryTemplatingEnabledKey = "__BeginCollectionItem_jQuery";

       public static MvcHtmlString CollectionItemJQueryTemplate<TModel, TCollectionItem>(this HtmlHelper<TModel> html,

                                                                                   string partialViewName,

                                                                                   TCollectionItem modelDefaultValues)

       {

           ViewDataDictionary<TCollectionItem> viewData = new ViewDataDictionary<TCollectionItem>(modelDefaultValues);

           viewData.Add(JQueryTemplatingEnabledKey, true);

           return html.Partial(partialViewName, modelDefaultValues, viewData);

       }

   }

}

MovieEntryEditor.cshtm部分视图



@using VariableCollection.Extension

@model VariableCollection.Models.Movie

 

<li style="padding-bottom: 15px;">

   @using (Html.BeginCollectionItem("FavouriteMovies"))

   {

       <img src="@Url.Content("~/Content/images/draggable-icon.png")" style="cursor: move" alt=""/>

 

       @Html.LabelFor(model => model.Title)

       @Html.EditorFor(model => model.Title)

       @Html.ValidationMessageFor(model => model.Title)

 

       @Html.LabelFor(model => model.Rating)

       @Html.EditorFor(model => model.Rating)

       @Html.ValidationMessageFor(model => model.Rating)

 

       <a href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  onclick=" $(this).parent().remove(); ">删除行</a>

   }

</li>

HomeController



public ActionResult EditJqueryTemplate()

{

   return View(CurrentUser);

}


[HttpPost]

public ActionResult EditJqueryTemplate(User user)

{

   if (!this.ModelState.IsValid)

   {

       return View(user);

   }

   CurrentUser = user;

   return RedirectToAction("Display");

}

EditJqueryTemplate.cshtml完整代码如下:



@using VariableCollection.Extension

@using VariableCollection.Models

@model VariableCollection.Models.User

 

@{

   ViewBag.Title = "EditJqueryTemplate";

   Layout = "~/Views/Shared/_Layout.cshtml";

}

 

<h2>EditJqueryTemplate</h2>

 

@using (Html.BeginForm())

{

   @Html.ValidationSummary(true)

   <fieldset>

       <legend>最喜欢看的电影</legend>

       @Html.HiddenFor(model => model.Id)

       <div class="editor-label">

           @Html.LabelFor(model => model.Name)

       </div>

       <div class="editor-field">

           @Html.EditorFor(model => model.Name)

           @Html.ValidationMessageFor(model => model.Name)

       </div>

   </fieldset>

   

   <fieldset>

       <legend>最喜欢看的电影</legend>

       @if (Model.FavouriteMovies == null || Model.FavouriteMovies.Count == 0)

       {

           <p>没有喜欢看的电影~~</p>

       }

       <ul id="movieEditor" style="list-style-type: none">

           @if (Model.FavouriteMovies != null)

           {

               foreach (Movie movie in Model.FavouriteMovies)

               {

                   Html.RenderPartial("MovieEntryEditor", movie);

               }

           }

       </ul>

               

       <a id="addAnother" href="#" rel="external nofollow"  rel="external nofollow"  rel="external nofollow"  >添加</a>

   </fieldset>

   <p>

       <input type="submit" value="提交" />

   </p>

}

 

@section scripts

{

   <script src="~/Scripts/jquery.tmpl.min.js"></script>

   

   <script type="text/x-jquery-tmpl" id="movieTemplate">

           @Html.CollectionItemJQueryTemplate("MovieEntryEditor", new Movie())

   </script>

 

   <script type="text/javascript">

           $(function () {

               $("#movieEditor").sortable();

 

               $('#addAnother').click(function() {

                   viewModel.addNew();

               });

           });

 

           var viewModel = {

               addNew: function () {

                   $("#movieEditor").append($("#movieTemplate").tmpl({ index: viewModel._generateGuid() }));

               },

 

               _generateGuid: function () {

                   // Source: http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/105074#105074

                   return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {

                       var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);

                       return v.toString(16);

                   });

               }

           };

   </script>

}