【问题标题】:reusable checkbox partial view可重复使用的复选框部分视图
【发布时间】:2015-03-14 01:28:36
【问题描述】:

我有一个局部视图,它使用类列表 (CheckBoxListModel) 和字符串和布尔值来创建复选框列表。该代码用于创建复选框,并在页面发布时将选定的复选框发送回控制器。我正在尝试找到一种方法来使我的部分可重用。正如您在代码中看到的那样,我发送了部分完整模型,这可以在页面发布时获取更新的复选框。我试图发送我的模型的 CheckBoxListModel,但它不起作用,因为当它创建复选框时,名称不正确。我想通过向它发送一个 CheckBoxListModel 来重用部分,这样我就不必在每次需要一组复选框时都创建一个单独的部分。

我尝试将_CheckBoxListPartial.cshtml改为

    @model MySite.Models.ViewModels.CheckBoxListModel
    ...
    @Html.EditorFor(x => x.CheckBoxes)
    ...

但没有 clmReturnOptions 复选框名称最终为 name="CheckBoxes[0].isChecked" 而不是 name="clmReturnOptions.CheckBoxes[0].isChecked" 因此当页面发布时它们不会在模型中更新回到控制器。

我一直在查看:http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx/,但如果不将整个模型发送到我的部分,似乎仍然无法让复选框工作。

CheckBoxListModel.cs

        public class CheckBoxListModel: ICheckBoxList
        {
            public IList<CheckBoxModel> CheckBoxes { get; set; }
            public string CheckBoxListTitle { get; set; }

            public CheckBoxListModel()
            {
            }
        }

        public class CheckBoxModel
        {
            public string CheckBoxName { get; set; }
            public string DisplayName { get; set; }
            public bool isChecked { get; set; }

            public CheckBoxModel()
            { }

            public CheckBoxModel(string checkboxname, string displayname, bool ischecked)
            {
                CheckBoxName = checkboxname;
                DisplayName = displayname;
                isChecked = ischecked;
            }
        }

        public interface ICheckBoxList
        {
            IList<CheckBoxModel> CheckBoxes { get; set; }
            string CheckBoxListTitle { get; set; }
        }

ReportFilterViewModel.cs

        public class ReportFilterViewModel
        {
            public ReportFilterViewModel()
            {
                clmReturnOptions = new CheckBoxListModel();
            }

            public CheckBoxListModel clmReturnOptions { get; set; }
        }

filters.cshtml

    @model MySite.Areas.Reports.Models.ViewModels.ReportFilterViewModel
    ...
        @if (Model.Filters.IsReturnsOptionsAvailable)
        {
            Html.RenderPartial("_CheckBoxFilterPartial", Model.clmReturnOptions);
        }
    ...

_CheckBoxFilterPartial.cshtml

    @model MySite.Areas.Reports.Models.ViewModels.ICheckBoxList

    @{
        Layout = null;
    }

    <!DOCTYPE html>
    <html>
    <head>
        <title>Returns Options</title>
    </head>
    <body>
        <div class="col-md-4">
            <div class="plm prm ptm pbm configureCellSplitBG configureCellSplitBG-outline mtm">
                <div class="row mlm mrm">
                    <h6>@Model.CheckBoxListTitle</h6>
                </div>
                @Html.EditorFor(x => x.CheckBoxes)
            </div>
        </div>
    </body>
    </html>

CheckBoxModel.cshtml

    @model MySite.Areas.Reports.Models.ViewModels.CheckBoxModel
    <div class="row mlm mrm">
        <div class="form-group">
            <label class="checkbox">
                @Html.CheckBoxFor(x => x.isChecked, new { @data_toggle = "checkbox" })
                @Html.LabelFor(x => x.CheckBoxName, Model.DisplayName)
                @Html.HiddenFor(x => x.CheckBoxName)
            </label>
        </div>
    </div>

更新 当我查看源代码时,我可以看到复选框名称仍然是:name="CheckBoxes[0].isChecked" 因此,当模型返回控制器时,列表为空

我所做的另一项更改是将 CheckBoxListModel.cs 从 MySite.Models.ViewModels 移动到 MySite.Areas.Reports.Models,因为其他所有内容都在 reports.models 下。

问题似乎是局部视图。如果我将@Html.EditorFor(x =&gt; x.clmReturnOptions.CheckBoxes) 放在我的主页中,则会使用全名创建复选框并正确更新。一旦我尝试在部分视图中使用 EditorFor,复选框名称就会更改,并且它们的链接会返回到模型中断。我想在局部视图中显示它,这样我就不必在我想要复选框列表的任何地方添加所有 ui 格式。

我已经更新了上面的代码

【问题讨论】:

    标签: c# asp.net-mvc checkbox partial


    【解决方案1】:

    创建一个可以访问IList&lt;CheckBoxModel&gt;的接口

    public interface ICheckBoxList
    {
        IList<CheckBoxModel> CheckBoxes { get; set; }
    }
    

    CheckBoxListModel 实现该接口

    public class CheckBoxListModel:ICheckBoxList
    {...
    

    您的 _CheckBoxListPartial.cshtml 部分视图将使用新接口作为其模型

    @model MySite.Areas.Reports.Models.ViewModels.ICheckBoxList
    

    并将您的 EditorFor 更改为

    @Html.EditorFor(x => x.CheckBoxes)
    

    我在您的问题中找不到显示您如何包含 _CheckBoxListPartial 部分视图的代码,但您只需传递 ViewModel 的 clmReturnOptions 属性(ReportFilterViewModel 或其他)而不是整个模型。

    你应该很高兴。

    【讨论】:

    • 我进行了所有更改,但仍然无法正常工作。部分调用如下:@Html.RenderPartial("_CheckBoxFilterPartial", Model.clmReturnOptions)。我将在另一个答案中发布更新的代码,以确保我正确实施。
    • 问题似乎是局部视图。如果我将 @Html.EditorFor(x => x.clmReturnOptions.CheckBoxes) 放在我的主页中,则会使用全名创建复选框并正确更新。一旦我尝试在部分视图中使用 EditorFor,复选框名称就会更改,并且它们的链接会返回到模型中断。
    【解决方案2】:

    您需要将前缀传递给局部视图,以便正确命名元素

    @if (Model.Filters.IsReturnsOptionsAvailable)
    {
      Html.RenderPartial("_CheckBoxFilterPartial", Model.clmReturnOptions, new ViewDataDictionary
      {
        TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "clmReturnOptions" }
      })
    }
    

    您还可以编写一个自定义的 html 帮助程序来简化此操作

    public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string partialViewName)
    {
      string name = ExpressionHelper.GetExpressionText(expression);
      object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
      var viewData = new ViewDataDictionary(helper.ViewData)
      {
        TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = name }
      };
      return helper.Partial(partialViewName, model, viewData);
    }
    

    并用作

    @Html.PartialFor(m => m.clmReturnOptions, "_CheckBoxFilterPartial")
    

    【讨论】:

    • 我之前没有创建过助手,但认为它只是助手文件夹中的一个静态类。我以为我所有的使用文件都是正确的,但不断收到此错误:'System.Web.Mvc.HtmlHelper' 不包含'Partial' 的定义,并且没有扩展方法'Partial' 接受类型的第一个参数可以找到“System.Web.Mvc.HtmlHelper”(您是否缺少 using 指令或程序集引用?)
    • 本站使用.net 4,需要使用System.Web.Mvc.Html;我让你的第一个例子工作,但我似乎无法让助手工作。我可以单步执行代码,它通过 CheckBoxModel.cshtml 运行 3 次(每个复选框一次),但是当页面显示时没有复选框并且当我查看页面源代码时没有它的位置。任何想法为什么它会运行代码但不会在页面上生成?
    • 助手只是在做第一个代码块正在做的事情(即添加HtmlFieldPrefix)并且对我有用,所以不确定还有什么问题。
    猜你喜欢
    • 1970-01-01
    • 2017-06-06
    • 1970-01-01
    • 1970-01-01
    • 2015-10-30
    • 2019-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多