zoukankan      html  css  js  c++  java
  • 如何自定义MVC控件?

    今天公司要写学习总结,想着想着还是先写一篇关于MVC内部什么东东的博客整理整理再发表吧,一举两得。

    之前写过了路由、过滤器等。今天就研究一下怎么自定义MVC控件吧。

    本人技术小菜,不喜勿喷。。。。。(说这句话通常有两种情况,一种是牛人谦虚的说法,一种是怕受伤害提前准备个挡箭牌)

    首先我们先去熟知一下MVC内部的那些控件是怎么实现的。

    首先,Input标签是大佬,我给各位看管来上一小段Password的吧。

     1      
     2     public static class InputExtensions {
     3    public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name) {
     4             return Password(htmlHelper, name, null /* value */);
     5         }
     6 
     7         public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value) {
     8             return Password(htmlHelper, name, value, null /* htmlAttributes */);
     9         }
    10 
    11         public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value, object htmlAttributes) {
    12             return Password(htmlHelper, name, value, HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
    13         }
    14 
    15         public static MvcHtmlString Password(this HtmlHelper htmlHelper, string name, object value, IDictionary<string, object> htmlAttributes) {
    16             return PasswordHelper(htmlHelper, null /* metadata */, name, value, htmlAttributes);
    17         }
    18 
    19         [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures", Justification = "This is an appropriate nesting of generic types")]
    20         public static MvcHtmlString PasswordFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression) {
    21             return PasswordFor(htmlHelper, expression, null /* htmlAttributes */);
    22         }
    23 }
    InputExtensions

    这定义的都是扩展方法,实现了重载,我们看到最后一个方法调用的是PasswordHelper 方法

    1         private static MvcHtmlString PasswordHelper(HtmlHelper htmlHelper, ModelMetadata metadata, string name, object value, IDictionary<string, object> htmlAttributes) {
    2             return InputHelper(htmlHelper, InputType.Password, metadata, name, value, false /* useViewData */, false /* isChecked */, true /* setId */, true /* isExplicitValue */, htmlAttributes);
    3         }

    但其最终调用的还是InputHelper方法,我们可以展开看看.....

     1         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) {
     2             string fullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
     3             if (String.IsNullOrEmpty(fullName)) {
     4                 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name");
     5             }
     6 
     7             TagBuilder tagBuilder = new TagBuilder("input");
     8             tagBuilder.MergeAttributes(htmlAttributes);
     9             tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType));
    10             tagBuilder.MergeAttribute("name", fullName, true);
    11 
    12             string valueParameter = Convert.ToString(value, CultureInfo.CurrentCulture);
    13             bool usedModelState = false;
    14 
    15             switch (inputType) {
    16                 case InputType.CheckBox:
    17                     bool? modelStateWasChecked = htmlHelper.GetModelStateValue(fullName, typeof(bool)) as bool?;
    18                     if (modelStateWasChecked.HasValue) {
    19                         isChecked = modelStateWasChecked.Value;
    20                         usedModelState = true;
    21                     }
    22                     goto case InputType.Radio;
    23                 case InputType.Radio:
    24                     if (!usedModelState) {
    25                         string modelStateValue = htmlHelper.GetModelStateValue(fullName, typeof(string)) as string;
    26                         if (modelStateValue != null) {
    27                             isChecked = String.Equals(modelStateValue, valueParameter, StringComparison.Ordinal);
    28                             usedModelState = true;
    29                         }
    30                     }
    31                     if (!usedModelState && useViewData) {
    32                         isChecked = htmlHelper.EvalBoolean(fullName);
    33                     }
    34                     if (isChecked) {
    35                         tagBuilder.MergeAttribute("checked", "checked");
    36                     }
    37                     tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
    38                     break;
    39                 case InputType.Password:
    40                     if (value != null) {
    41                         tagBuilder.MergeAttribute("value", valueParameter, isExplicitValue);
    42                     }
    43                     break;
    44                 default:
    45                     string attemptedValue = (string)htmlHelper.GetModelStateValue(fullName, typeof(string));
    46                     tagBuilder.MergeAttribute("value", attemptedValue ?? ((useViewData) ? htmlHelper.EvalString(fullName) : valueParameter), isExplicitValue);
    47                     break;
    48             }
    49 
    50             if (setId) {
    51                 tagBuilder.GenerateId(fullName);
    52             }
    53 
    54             // If there are any errors for a named field, we add the css attribute.
    55             ModelState modelState;
    56             if (htmlHelper.ViewData.ModelState.TryGetValue(fullName, out modelState)) {
    57                 if (modelState.Errors.Count > 0) {
    58                     tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName);
    59                 }
    60             }
    61 
    62             tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata));
    63 
    64             if (inputType == InputType.CheckBox) {
    65                 // Render an additional <input type="hidden".../> for checkboxes. This
    66                 // addresses scenarios where unchecked checkboxes are not sent in the request.
    67                 // Sending a hidden input makes it possible to know that the checkbox was present
    68                 // on the page when the request was submitted.
    69                 StringBuilder inputItemBuilder = new StringBuilder();
    70                 inputItemBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing));
    71 
    72                 TagBuilder hiddenInput = new TagBuilder("input");
    73                 hiddenInput.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden));
    74                 hiddenInput.MergeAttribute("name", fullName);
    75                 hiddenInput.MergeAttribute("value", "false");
    76                 inputItemBuilder.Append(hiddenInput.ToString(TagRenderMode.SelfClosing));
    77                 return MvcHtmlString.Create(inputItemBuilder.ToString());
    78             }
    79 
    80             return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing);
    81         }
    InputHelper

    该方法主要通过传递来的Input类型,还有一些name,value以及一些判断的界定来生产一个Input标签,最后返回一个MvcHtmlString对象。

    其中实现我们就不做一一分析了,只是看看大概是如何实现的。

    接下来我们自己定义一个简单的Input标签,类型为submit即提交的按钮。

     1 namespace System.Web.Mvc.Html      
     2 {
     3     public static class SubmitExtention
     4     {
     5         public const string DefaultSubmitValue = "提交";
     6 
     7         public static MvcHtmlString Submit(this HtmlHelper htmlHelper)
     8         {
     9             return Submit(htmlHelper);
    10         }
    11 
    12         public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string value)
    13         {
    14             return Submit(htmlHelper, null, value);
    15         }
    16 
    17         public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string name, string value)
    18         {
    19             return Submit(htmlHelper, name, value, null);
    20         }
    21 
    22         public static MvcHtmlString Submit(this HtmlHelper htmlHelper, string name, string value, IDictionary<string, string> attributes)
    23         {
    24             TagBuilder tag = new TagBuilder("input");
    25             tag.Attributes.Add("type", "submit");
    26 
    27             if (!string.IsNullOrEmpty(name))
    28             {
    29                 tag.Attributes.Add("name", name);
    30             }
    31 
    32             if (!string.IsNullOrEmpty(value))
    33             {
    34                 tag.Attributes.Add("value", value);
    35             }
    36             else
    37             {
    38                 tag.Attributes.Add("value", DefaultSubmitValue);
    39             }
    40 
    41             if (null != attributes)
    42             {
    43                 foreach (var attr in attributes)
    44                 {
    45                     tag.Attributes.Add(attr.Key, attr.Value);
    46                 }
    47             }
    48             return MvcHtmlString.Create(tag.ToString());
    49         }
    50     }
    51 }

    好了,我们去视图里看看吧。

    点出来了吧,小伙伴们惊喜吗?

    呵呵,其实一点都不惊喜,不久一个扩展方法吗?

    不积跬步无以至千里,慢慢来,以后的路还很长,写博客只是为了总结,忘了的时候翻出来看看,温习温习,权当做笔记咯。

    注意:

     在视图配置文件中没有添加引用的情况下,小伙伴们可能点不出。

    如果不行,你们还是把命名空间改为System.Web.Mvc.Html,像我这样,不然是点不出来的。  

  • 相关阅读:
    codechef BIBOARD
    Tree
    NOIWC2021总结
    星际穿越
    GDKOI总结
    lg4229
    P3320 [SDOI2015]寻宝游戏
    P6670 [清华集训2016] 汽水
    P6326 Shopping
    P3060 [USACO12NOV]Balanced Trees G
  • 原文地址:https://www.cnblogs.com/yangda/p/3346812.html
Copyright © 2011-2022 走看看