标签:style blog class code java tar
在"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="#" 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="#" 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="#" >添加</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#105074return ‘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>
}
参考资料:
※ Editing Variable Length Reorderable Collections in ASP.NET MVC –
Part 2: jQuery Templates
MVC批量更新,使用jQuery Template,布布扣,bubuko.com
标签:style blog class code java tar
原文地址:http://www.cnblogs.com/darrenji/p/3717770.html