TextBoxFor控件的扩展---Bootstrap在mvc上的应用
TextBoxFor控件的问题:
1:自带了样式,再用bootstrap样式会有冲突。
2:要加水印,js事件,限制输入长度比较麻烦。
因此需要对textboxfor控件进行扩展。
目标:
1:能使用bootstrap样式。
2:能复用mvc的验证。
3:可以方便的添加水印。
4:能限制输入字符的长度。
5:采用一些命名约定,使用扩展控件。(说白了,就是日期类型的直接给上边加上调用日期控件的调用。)
解决方案
最容易想到的解决办法就是直接写个扩展方法,进行字符串拼接生成控件。使用的时候:@BootStrap.TextBoxFor(u=>u.Email)
最终生成:
<input class="form-control" data-val="true" data-val-length="字段 邮箱 必须是最大长度为 50 的字符串。" data-val-length-max="50" data-val-regex="字段 邮箱 必须与正则表达式“.+”匹配。" data-val-regex-pattern=".+" data-val-required="邮箱 字段是必需的。" id="Email" maxlength="50" name="Email" type="text" value="taibaizhou@163.com"></input>
<span class="field-validation-valid help-block" data-valmsg-for="Email" data-valmsg-replace="true"></span>
实现时候,悲催了。发现很难直接获取属性的验证信息,难道要自己再写反射,读取特性。生成对应的验证信息。
另一条路,借助mvc的htmlhelper来完成了。
public static MvcHtmlString BsTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
Expression<Func<TModel, TProperty>> expression,string css="", string placeholder="")
{
TagBuilder tagBuilder = new TagBuilder("input");
ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
//tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata));
string name = ExpressionHelper.GetExpressionText(expression);
//var vas = htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata);
htmlHelper.ValidateFor(expression);
tagBuilder.MergeAttribute("name",name);
tagBuilder.GenerateId(name);
tagBuilder.MergeAttribute("type","text");
//核心代码,直接通过这个方法可以获取属性上的验证信息,如:“data-val= ....”。有一点要注意,在一个属性上,调用了这个方法完成后。mvc底层代码会自动释放这个验证对象。也就是说,一个属性的输入文本框只会第一个上边会生成相关的验证。
var vas = htmlHelper.GetUnobtrusiveValidationAttributes(name,metadata);
if (!string.IsNullOrEmpty(placeholder)) { tagBuilder.MergeAttribute("placeholder",placeholder); }
//string类型,看有没长度限制,如果有,增加maxlength,minlength
if (metadata.ModelType == typeof (string))
{
var len = metadata.ContainerType.GetProperty(name).GetCustomAttribute(typeof(StringLengthAttribute));
if (len != null)
{
var stringlength = (StringLengthAttribute) len;
if (stringlength.MaximumLength > )
{
tagBuilder.MergeAttribute("maxlength", stringlength.MaximumLength.ToString());
}
if (stringlength.MinimumLength > )
{
tagBuilder.MergeAttribute("minlength", stringlength.MinimumLength.ToString());
}
}
}
//如果model值不为,null,进行赋值。
if (metadata.Model != null)
{
todo:还要完善。
tagBuilder.MergeAttribute("value",metadata.Model.ToString());
}
tagBuilder.MergeAttributes(vas);
tagBuilder.AddCssClass("form-control");
if (!string.IsNullOrEmpty(css))
{
tagBuilder.AddCssClass(css);
}
//约定,属性名以day或者date结束的属性为日体,为其增加日期选择功能。
if (name.ToLower().EndsWith("day") || name.ToLower().EndsWith("date"))
{
tagBuilder.MergeAttribute("onclick", "WdatePicker()");
}
return new MvcHtmlString(tagBuilder.ToString());
}
最终实现效果:

View部分代码:
<div class="form-group">
@Html.BsLabelFor(model => model.Email)
<div class="col-xs-10">
@*@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })*@
@Html.BsTextBoxFor(model=>model.Email)
@Html.ValidationMessageFor(model => model.Email, "", new { @class = "help-block" }) </div>
</div>
<div class="form-group">
@Html.BsLabelFor(model => model.Salary)
<div class="col-xs-2 input-group" >
<div class="input-group-addon">$</div>
@Html.BsTextBoxFor(model => model.Salary)
<div class="input-group-addon">.00</div>
</div><div class="col-xs-8">
@Html.ValidationMessageFor(model => model.Salary, "", new { @class = "help-block" })
</div>
</div>
<div class="form-group">
@Html.BsLabelFor(model => model.Code)
<div class="col-xs-2">
@Html.BsTextBoxFor(model => model.Code)
</div><div class="col-xs-8">
@Html.ValidationMessageFor(model => model.Code, "", new { @class = "help-block" })
</div>
</div>
<div class="form-group">
@Html.BsLabelFor(model => model.BirthDay)
<div class="col-xs-2 input-group">
@Html.BsTextBoxFor(model => model.BirthDay)<div class="input-group-addon" onclick="WdatePicker({ el: 'BirthDay' })">
<span class="glyphicon glyphicon-th"></span>
</div>
</div><div class="col-xs-8">
@Html.ValidationMessageFor(model => model.BirthDay)
</div>
</div>
viewModel代码:
public class VerifyModel
{
public Guid Id { get; set; }
[DisplayName("用户名")]
[Required]
[StringLength()]
[Remote("CheckName", "Form")]
public string UserName { get; set; }
[DisplayName("密码")]
[Required]
[StringLength(,MinimumLength = )]
[DataType(DataType.Password)]
public string PassWord { get; set; }
[DataType(DataType.Password)]
[System.ComponentModel.DataAnnotations.Compare("PassWord", ErrorMessage = "两次输入密码不一致")]
[DisplayName("确认密码")]
public virtual string ConfirmPassWord { get; set; }
[StringLength()]
[DisplayName("邮箱")]
[Required]
[DataType(DataType.EmailAddress)]
[RegularExpression(@".+")]
public string Email { get; set; }
[RegularExpression(@"1\d{10}", ErrorMessage = "请输入正确的手机号码")]
[DisplayName("手机")]
[Required]
public string Phone { get; set; }
[DisplayName("薪水")]
[Required]
public decimal Salary { get; set; }
[RegularExpression(@"d{6}", ErrorMessage = "邮编为六位数字")]
[DisplayName("邮编")]
[Required]
public string Code { get; set; }
[DisplayName("生日")]
[Required]
public DateTime BirthDay { get; set; }
}
最后:
配合T4模板,采用一些命名约定能更快捷的生成各种表单页面。
TextBoxFor控件的扩展---Bootstrap在mvc上的应用的更多相关文章
- MvcPager分页控件以适用Bootstrap
随笔- 9 文章- 0 评论- 33 修改MvcPager分页控件以适用Bootstrap 效果(含英文版,可下载) 软件开发分页效果必不可少,对于Asp.Net MVC 而言,MvcPag ...
- 验证控件插图扩展控件ValidatorCalloutExtender(用于扩展验证控件)和TextBoxWatermarkExtender
<asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptMan ...
- (转)C# WinForm中 获得当前鼠标所在控件 或 将窗体中鼠标所在控件名显示在窗体标题上
原文地址:http://www.cnblogs.com/08shiyan/archive/2011/04/14/2015758.html /********************** * 课题:将窗 ...
- 使用NeatUpload控件实现ASP.NET大文件上传
使用NeatUpload控件实现ASP.NET大文件上传 一般10M以下的文件上传通过设置Web.Config,再用VS自带的FileUpload控件就可以了,但是如果要上传100M甚至1G的文件就不 ...
- 使用input:file控件在微信内置浏览器上传文件返回未显示选择的文件
使用input:file控件在微信内置浏览器上传文件返回未显示选择的文件 原来的写法: <input type="file" accept="image/x-png ...
- 【C#】使用IExtenderProvider为控件添加扩展属性,像ToolTip那样
申明: - 本文适用于WinForm开发 - 文中的“控件”一词是广义上的说法,泛指包括ToolStripItem.MenuItem在内单个界面元素,并不特指继承自Control类的狭义控件 用过To ...
- WPF中查找控件的扩展类
在wpf中查找控件要用到VisualTreeHelper类,但这个类并没有按照名字查找控件的方法,于是搜索网络,整理出下面这个类,感觉用起来很是方便. 贴出来,供大家参考. /// <summa ...
- WPF之花式控件功能扩展
文章默认你已经入门WPF了 WPF日常开发,经常遇到默认的控件功能不满足需求,怎么办? No1. 自定义控件模板 平时开发中,经常遇到比较"俗"的需求,嫌弃控件默认的样子. ...
- asp.net ajax控件tab扩展,极品啊,秒杀其它插件
说明:asp.net ajax控件tab要设置width和height,而且在线文本编辑器放能够放入tab中,也必须是asp.net的控件型在线文本,例如fckeditor,下面是我设置好的配置. & ...
随机推荐
- Angularjs之如何在跨域请求中传输Cookie
一般情况我们在使用WebApi之类的技术时,都会遇到跨域的问题,这个只需要在服务端做一下处理即可. 如果这些GET或POST请求不需要传递Cookie数据的话,就没什么问题了,但如果需要,那么会发现 ...
- React Native初试:Windows下Andriod环境搭建
最近想写个App,又觉得Native App 太无趣了Web App又没那么成熟然后发现了Facebook在9月发布的React Native比较新奇,所以决定捣鼓看看: React Native为F ...
- Unknown class in Interface Builder file 解决方案
在用swift项目打包Framework时,在项目中使用包时,报错: Unknown class in Interface Builder file... 网上很多解决方案,都不适合我的场景 最终解决 ...
- android 反编译apktool工具
下载地址:http://pan.baidu.com/s/1bnHANtd 1.将编译的*.apk放在apktool的根目录下:2.双击“解压软件.bat”后,会提示完成:这样就反编译成功以:3.查看反 ...
- ES6新增值比较函数Object.is
在这之前我们比较值使用两等号 “==” 或 三等号“===”, 三等号更加严格,只要比较两方类型不同立即返回false. 另外,有且只有一个值不和自己相等,它是NaN 现在ES6又加了一个Object ...
- Nginx之location 匹配规则详解
有些童鞋的误区 1. location 的匹配顺序是“先匹配正则,再匹配普通”. 矫正: location 的匹配顺序其实是“先匹配普通,再匹配正则”.我这么说,大家一定会反驳我,因为按“先匹配普通, ...
- Eclipse RCP实用小技巧
1.插件Plugin工程的build.properties中增加一行,javacDefaultEncoding.. = UTF 2.插件Plugin工程的Runtime的classpath中加入.
- [To be translated] Nova:libvirt image 的生命周期
翻译自:http://www.pixelbeat.org/docs/openstack_libvirt_images/ The main stages of a Virtual Machine dis ...
- DPM检测模型 VoC-release 5 linux 下编译运行
(转载请注明作者和出处 楼燚(yì)航的blog :http://www.cnblogs.com/louyihang-loves-baiyan/ 未经允许请勿用于商业用途) DPM目前使非神经网络方法 ...
- save()、saveOrUpdate()、merge()的区别
一.Save() save()方法能够保存实体到数据库.假如两个实体之间有关系(例如employee表和address表有一对一关系),如果在没有事务的情况下调用这个方法保存employee这个实体, ...