带有CheckBoxFor扩展的MVC自定义TextBoxFor

时间:2015-07-31 11:04:16

标签: c# asp.net-mvc

我正在尝试将此剃刀代码转换为c#代码。但是,复选框回发有问题。

<div class="input-group">
   @Html.TextBoxFor(model => model.Property1, new { @class = "form-control js-template-text", data_val = "false" }
   <span class="input-group-addon">
       @Html.CheckBoxFor(model => model.Property2, new { data_val = "false" })
       @Html.HiddenFor(model => model.Property2)
       <span class="glyphicon glyphicon-phone glyphicon-green"></span>
   </span>
</div>

这个标记的工作正常。 但是这个c#代码生成的标记没有。两种方法生成的标记都是相同的。 我的问题是:代码中需要进行哪些修改(如果有的话),以便浏览器发送正确的复选框值。

    private static MvcHtmlString CreateTextBoxCheckBoxFor<TModel>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, string>> textBoxExpression, Expression<Func<TModel, bool>> checkBoxExpression, IGlyphIcon checkBoxGlyphIcon = null, IDictionary<string, object> htmlAttributes = null, IDictionary<string, object> textBoxHtmlAttributes = null, IDictionary<string, object> checkBoxHtmlAttributes = null)
    {
        var sb = new StringBuilder();

        #region OuterDiv

        var outerDivTag = new TagBuilder("div");
        outerDivTag.MergeAttributes(htmlAttributes);
        outerDivTag.AddCssClass("input-group");
        sb.AppendLine(outerDivTag.ToString(TagRenderMode.StartTag));

        #endregion OuterDiv

        #region TextBox

        var textBoxName = ExpressionHelper.GetExpressionText(textBoxExpression);
        var textBoxFullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(textBoxName);
        var textBoxId = TagBuilder.CreateSanitizedId(textBoxFullName);

        var textBoxMetaData = ModelMetadata.FromLambdaExpression(textBoxExpression, htmlHelper.ViewData);
        var textBoxValue = textBoxMetaData.Model.ToString();

        var textBoxTag = new TagBuilder("input");
        textBoxTag.Attributes.Add("type", "text");
        textBoxTag.Attributes.Add("class", "form-control");
        textBoxTag.Attributes.Add("name", textBoxFullName);
        textBoxTag.Attributes.Add("id", textBoxId);
        textBoxTag.Attributes.Add("value", textBoxValue);

        // get data annotation/client side scripts attributes
        var textkBoxValidationAttributes = htmlHelper.GetUnobtrusiveValidationAttributes(textBoxFullName, textBoxMetaData);
        foreach (var key in textkBoxValidationAttributes.Keys)
        {
            textBoxTag.Attributes.Add(key, textkBoxValidationAttributes[key].ToString());
        }

        textBoxTag.MergeAttributes(textBoxHtmlAttributes, true);
        sb.AppendLine(textBoxTag.ToString(TagRenderMode.SelfClosing));

        #endregion TextBox

        #region CheckBox

        var checkBoxSpan = new TagBuilder("span");
        checkBoxSpan.Attributes.Add("class", "input-group-addon");

        var checkBoxName = ExpressionHelper.GetExpressionText(checkBoxExpression);
        var checkBoxFullName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(checkBoxName);
        var checkBoxId = TagBuilder.CreateSanitizedId(checkBoxFullName);

        var checkBoxMetaData = ModelMetadata.FromLambdaExpression(checkBoxExpression, htmlHelper.ViewData);
        var checkBoxValue = checkBoxMetaData.Model.ToString().ToLower();

        var checkBoxTag = new TagBuilder("input");
        checkBoxTag.Attributes.Add("type", "checkbox");
        checkBoxTag.Attributes.Add("name", checkBoxFullName);
        checkBoxTag.Attributes.Add("id", checkBoxId);
        checkBoxTag.Attributes.Add("value", checkBoxValue);
        if (checkBoxValue.Equals("true", StringComparison.InvariantCultureIgnoreCase))
        {
            checkBoxTag.Attributes.Add("checked", "checked");
        }

        // get data annotation/client side scripts attributes
        var validationAttributes = htmlHelper.GetUnobtrusiveValidationAttributes(checkBoxFullName, checkBoxMetaData);
        foreach (var key in validationAttributes.Keys)
        {
            checkBoxTag.Attributes.Add(key, validationAttributes[key].ToString());
        }

        checkBoxTag.MergeAttributes(checkBoxHtmlAttributes, true);

        // to keep track of checkbox postbacks, create hidden input for checkbox
        var checkBoxHiddenTag = new TagBuilder("input");
        checkBoxHiddenTag.Attributes.Add("name", checkBoxFullName);
        checkBoxHiddenTag.Attributes.Add("id", checkBoxId);
        checkBoxHiddenTag.Attributes.Add("type", "hidden");
        checkBoxHiddenTag.Attributes.Add("value", checkBoxValue.Equals("true", StringComparison.InvariantCultureIgnoreCase) ? "True" : "False");

        sb.AppendLine(checkBoxSpan.ToString(TagRenderMode.StartTag));
        sb.AppendLine(checkBoxTag.ToString(TagRenderMode.SelfClosing));
        sb.AppendLine(checkBoxHiddenTag.ToString(TagRenderMode.SelfClosing));

        #endregion CheckBox

        #region GlyphIcon

        if (checkBoxGlyphIcon != null)
        {
            var checkBoxGlyphIconSpan = new TagBuilder("span");
            checkBoxGlyphIconSpan.Attributes.Add("class", checkBoxGlyphIcon.CssClass);
            sb.AppendLine(checkBoxGlyphIconSpan.ToString(TagRenderMode.StartTag));
            sb.AppendLine(checkBoxGlyphIconSpan.ToString(TagRenderMode.EndTag));
        }

        #endregion GlyphIcon

        sb.AppendLine(checkBoxSpan.ToString(TagRenderMode.EndTag));
        sb.AppendLine(outerDivTag.ToString(TagRenderMode.EndTag));
        var result = MvcHtmlString.Create(sb.ToString());
        return result;
    }

非常感谢任何方向/反馈。

1 个答案:

答案 0 :(得分:0)

首先,您的视图代码包含console.log(longestWord("Using the JavaScript language bademnostalgiastic"));,这有点无意义,应该删除。 @Html.HiddenFor(model => model.Property2)方法正确地为属性呈现值为CheckBoxFor()的隐藏输入。幸运的是,False忽略了此输入(否则您只会回发该属性的原始值)。

您声称​​&#34;两种方法生成的标记相同&#34; 不正确,您的代码生成一个复选框和一个隐藏输入,其中隐藏输入的值由于您使用

,因此ID为该属性的初始值
DefaultModelBinder

这意味着

  1. 初始值为checkBoxHiddenTag.Attributes.Add("value", checkBoxValue.Equals("true", StringComparison.InvariantCultureIgnoreCase) ? "True" : "False"); ,您发布的复选框已经过检查 返回falseTrue生成False(仅限模型绑定器) 使用第一个值)
  2. 初始值为true,您发布的复选框已取消选中 返回false,结果为False
  3. 初始值为false,您发布的复选框已经过检查 返回trueTrue,结果为False
  4. 初始值为true,您发布的复选框未经过检查 返回true生成True(问题出在哪里)
  5. 您的代码还存在许多其他问题,包括如果由于验证错误而返回视图,则不会绑定到true

    如果您想手动完成所有这些操作,我建议您研究source code,但所有这些都可以通过使用内置方法进行简化

    ModelState