如何自定义MVC控件?
今天公司要写学习总结,想着想着还是先写一篇关于MVC内部什么东东的博客整理整理再发表吧,一举两得。
之前写过了路由、过滤器等。今天就研究一下怎么自定义MVC控件吧。
本人技术小菜,不喜勿喷。。。。。(说这句话通常有两种情况,一种是牛人谦虚的说法,一种是怕受伤害提前准备个挡箭牌)
首先我们先去熟知一下MVC内部的那些控件是怎么实现的。
首先,Input标签是大佬,我给各位看管来上一小段Password的吧。
public static class InputExtensions {
public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name) {
return Password(htmlHelper, name, null /* value */);
} public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value) {
return Password(htmlHelper, name, value, null /* htmlAttributes */);
} public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes) {
return Password(htmlHelper, name, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
} public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes) {
return PasswordHelper(htmlHelper, null /* metadata */, name, value, htmlAttributes);
} [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
public static MvcHtmlString PasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) {
return PasswordFor(htmlHelper, expression, null /* htmlAttributes */);
}
}
InputExtensions
这定义的都是扩展方法,实现了重载,我们看到最后一个方法调用的是PasswordHelper 方法
private static MvcHtmlString PasswordHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, object value, IDictionary<string, object> htmlAttributes) {
return InputHelper(htmlHelper, InputType.Password, metadata, name, value, false /* useViewData */, false /* isChecked */, true /* setId */, true /* isExplicitValue */, htmlAttributes);
}
但其最终调用的还是InputHelper方法,我们可以展开看看.....
private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, IDictionary<string, object> htmlAttributes) {
string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
if (String.IsNullOrEmpty(fullName)) {
throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
} TagBuilder tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttributes(htmlAttributes);
tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
tagBuilder.MergeAttribute("name", fullName, true); string valueParameter = Convert.ToString(value, CultureInfo.CurrentCulture);
bool usedModelState = false; switch (inputType) {
case InputType.CheckBox:
bool? modelStateWasChecked = htmlHelper.GetModelStateValue(fullName, typeof(bool)) as bool?;
if (modelStateWasChecked.HasValue) {
isChecked = modelStateWasChecked.Value;
usedModelState = true;
}
goto case InputType.Radio;
case InputType.Radio:
if (!usedModelState) {
string modelStateValue = htmlHelper.GetModelStateValue(fullName, typeof(string)) as string;
if (modelStateValue != null) {
isChecked = String.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
usedModelState = true;
}
}
if (!usedModelState && useViewData) {
isChecked = htmlHelper.EvalBoolean(fullName);
}
if (isChecked) {
tagBuilder.MergeAttribute("checked", "checked");
}
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
break;
case InputType.Password:
if (value != null) {
tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
}
break;
default:
string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName) : valueParameter), isExplicitValue);
break;
} if (setId) {
tagBuilder.GenerateId(fullName);
} // If there are any errors for a named field, we add the css attribute.
ModelState modelState;
if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState)) {
if (modelState.Errors.Count > ) {
tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
} tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata)); if (inputType == InputType.CheckBox) {
// Render an additional <input type="hidden".../> for checkboxes. This
// addresses scenarios where unchecked checkboxes are not sent in the request.
// Sending a hidden input makes it possible to know that the checkbox was present
// on the page when the request was submitted.
StringBuilder inputItemBuilder = new StringBuilder();
inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing)); TagBuilder hiddenInput = new TagBuilder("input");
hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
hiddenInput.MergeAttribute("name", fullName);
hiddenInput.MergeAttribute("value", "false");
inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
return MvcHtmlString.Create(inputItemBuilder.ToString());
} return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing);
}
InputHelper
该方法主要通过传递来的Input类型,还有一些name,value以及一些判断的界定来生产一个Input标签,最后返回一个MvcHtmlString对象。
其中实现我们就不做一一分析了,只是看看大概是如何实现的。
接下来我们自己定义一个简单的Input标签,类型为submit即提交的按钮。
namespace System.Web.Mvc.Html
{
public static class SubmitExtention
{
public const string DefaultSubmitValue = "提交"; public static MvcHtmlString Submit(this HtmlHelper htmlHelper)
{
return Submit(htmlHelper);
} public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string value)
{
return Submit(htmlHelper, null, value);
} public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string name, string value)
{
return Submit(htmlHelper, name, value, null);
} public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string name, string value, IDictionary<string, string> attributes)
{
TagBuilder tag = new TagBuilder("input");
tag.Attributes.Add("type", "submit"); if (!string.IsNullOrEmpty(name))
{
tag.Attributes.Add("name", name);
} if (!string.IsNullOrEmpty(value))
{
tag.Attributes.Add("value", value);
}
else
{
tag.Attributes.Add("value", DefaultSubmitValue);
} if (null != attributes)
{
foreach (var attr in attributes)
{
tag.Attributes.Add(attr.Key, attr.Value);
}
}
return MvcHtmlString.Create(tag.ToString());
}
}
}
好了,我们去视图里看看吧。
点出来了吧,小伙伴们惊喜吗?
呵呵,其实一点都不惊喜,不久一个扩展方法吗?
不积跬步无以至千里,慢慢来,以后的路还很长,写博客只是为了总结,忘了的时候翻出来看看,温习温习,权当做笔记咯。
注意:
在视图配置文件中没有添加引用的情况下,小伙伴们可能点不出。
如果不行,你们还是把命名空间改为System.Web.Mvc.Html,像我这样,不然是点不出来的。
如何自定义MVC控件?的更多相关文章
- Mvc自定义分页控件
MVC开发分页常常使用第三方控件,生成的分页HTML带有版权申明,虽然免费,但是总有的别扭.于是,某日,楼主闲来蛋疼,折腾了个自定义分页控件: 先来展示下效果图: 1>当分页不超过10页的时候, ...
- 9.2.2 .net framework下的MVC 控件的封装(下)
控件封装的部分说明 可能有人觉得应该前后端分离,我也承认这是应该的方向,我们也在考虑使用ng2等简化前端.但是,我们封装控件还是因为如下原因综合考虑的: 我们这是个框架,上面支撑了许多个应用,包含几百 ...
- FineUIMvc v1.4.0 发布了(ASP.NET MVC控件库)!
FineUIMvc v1.4.0 已经于 2017-06-30 发布,FineUIMvc 是基于 jQuery 的专业 ASP.NET MVC 控件库,是我们的新产品.由于和 FineUI(专业版)共 ...
- 安卓自定义组合控件--toolbar
最近在学习安卓APP的开发,用到了toolbar这个控件, 最开始使用时include layout这种方法,不过感觉封装性不好,就又改成了自定义组合控件的方式. 使用的工具为android stud ...
- Android自定义控件之自定义组合控件
前言: 前两篇介绍了自定义控件的基础原理Android自定义控件之基本原理(一).自定义属性Android自定义控件之自定义属性(二).今天重点介绍一下如何通过自定义组合控件来提高布局的复用,降低开发 ...
- asp.net webform 自定义分页控件
做web开发一直用到分页控件,自己也动手实现了个,使用用户自定义控件. 翻页后数据加载使用委托,将具体实现放在在使用分页控件的页面进行注册. 有图有真相,给个直观的认识: 自定义分页控件前台代码: & ...
- 9.2.1 .net framework下的MVC 控件的封装(上)
在写.net core下mvc控件的编写之前,我先说一下.net framework下我们MVC控件的做法. MVC下控件的写法,主要有如下三种,最后一种是泛型的写法,mvc提供的控件都是基本控件. ...
- arcgis api for js共享干货系列之二自定义Navigation控件样式风格
arcgis api for js默认的Navigation控件样式风格如下图: 这样的风格不能说不好,各有各的爱好,审美观,这里也不是重点,这里的重点是如何自定义一套自己喜欢的样式风格呢:自己自定义 ...
- C# DataGridView自定义分页控件
好些日子不仔细写C#代码了,现在主要是Java项目,C#.Net相关项目不多了,有点手生了,以下代码不足之处望各位提出建议和批评. 近日闲来无事想研究一下自定义控件,虽然之前也看过,那也仅限于皮毛,粗 ...
随机推荐
- Planner – 项目管理软件
http://www.appinn.com/planner/ Planner 是一款开源.易用.跨平台的项目管理软件.@appinn 二猪用了 OpenProject 几年,现在已经受够了它的各种 ...
- HtmlNodeType枚举
HtmlNodeType是一个枚举,用于说明一个节点的类型. 源代码如下所示: public enum HtmlNodeType { Document = 0, Element = 1, Commen ...
- 其中 (%{WORD:x_forword}|-) |表示或的意思
121.40.205.143 [30/Aug/2016:14:03:08 +0800] "GET /resources/images/favicon.ico HTTP/1.1" - ...
- 深入浅出Node.js (2) - 模块机制
2.1 CommonJS规范 2.1.1 CommonJS的出发点 2.1.2 CommonJS的模块规范 2.2 Node的模块实现 2.2.1 优先从缓存加载 2.2.2 路径分析和文件定位 2. ...
- Phoenix中Sequence的用法
Phoenix--HBase的JDBC驱动 序列(Sequence)是Phoenix提供的允许产生单调递增数字的一个SQL特性,序列会自动生成顺序递增的序列号,以实现自动提供唯一的主键值. 使用C ...
- 由闭包引起的对javascript代码可维护性的思考
在最近的编程实践中由闭包的使用引起了我对javascript代码可维护性的思考.面向对象的其中一个特性封装性通过封装可以降低类与类之间或模块与模块之间耦合性从而使我们的设计更加高内聚低耦合,在大规模的 ...
- Oracle SQL函数之聚组函数
AVG([distinct|all]x) [功能]统计数据表选中行x列的平均值. [参数]all表示对所有的值求平均值,distinct只对不同的值求平均值,默认为all 如果有参数distinct或 ...
- AIX-vi操作-提示Unknown terminal type的问题解决方法
AIX-vi操作-提示Unknown terminal type的问题解决方法AIX Version 5.3$ vi /etc/profilelinux: Unknown terminal type[ ...
- 阿里云RDS导入服务器数据库 XtraBackup
如果是centos系统,默认会开启selinux 一定需关闭selinux 解决方法:关闭它,打开/etc/selinux/config,把SELINUX=enforcing改为SELINUX=dis ...
- flex与js相互调用
1.flex调用js方法 调用方法例如:ExternalInterface.call("UploadComplete",oldName,uidName,_dir+"/&q ...