可重复使用的复选框部分视图
reusable checkbox partial view
我有一个部分视图,它使用 类 (CheckBoxModel) 的列表 (CheckBoxListModel) 以及字符串和布尔值来创建复选框列表。该代码用于创建复选框,并在页面发布时将选中的复选框发送回控制器。我正试图找到一种方法使我的部分可重用。正如您在代码中看到的那样,我发送了部分完整模型,这可以在页面发布时获取更新的复选框。我试图发送我的模型的 CheckBoxListModel,但它不起作用,因为当它创建复选框时名称不正确。我想通过向它发送一个 CheckBoxListModel 来重用部分,这样我就不必在每次需要一组复选框时都创建一个单独的部分。
我试图change_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>
更新
当我查看源代码时,我可以看到 CheckBox 名称仍然是:name="CheckBoxes[0].isChecked"
因此,当模型返回控制器时,列表为 null
1 我所做的其他更改是将 CheckBoxListModel.cs 从 MySite.Models.ViewModels 移动到 MySite.Areas.Reports.Models,因为其他所有内容都在 reports.models.
下
好像是局部视图的问题。如果我将 @Html.EditorFor(x => x.clmReturnOptions.CheckBoxes)
放在我的主页中,则会使用全名创建复选框并正确更新。一旦我尝试在局部视图中使用 EditorFor,复选框名称就会更改,并且 link 返回到模型中断。我想在局部视图中使用它,这样我就不必在我想要复选框列表的任何地方添加所有 ui 格式。
我更新了上面的代码
创建一个接口,提供对 IList<CheckBoxModel>
的访问
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
或其他)而不是整个模型。
你应该可以开始了。
您需要将前缀传递给分部视图,以便正确命名元素
@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")
我有一个部分视图,它使用 类 (CheckBoxModel) 的列表 (CheckBoxListModel) 以及字符串和布尔值来创建复选框列表。该代码用于创建复选框,并在页面发布时将选中的复选框发送回控制器。我正试图找到一种方法使我的部分可重用。正如您在代码中看到的那样,我发送了部分完整模型,这可以在页面发布时获取更新的复选框。我试图发送我的模型的 CheckBoxListModel,但它不起作用,因为当它创建复选框时名称不正确。我想通过向它发送一个 CheckBoxListModel 来重用部分,这样我就不必在每次需要一组复选框时都创建一个单独的部分。
我试图change_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>
更新
当我查看源代码时,我可以看到 CheckBox 名称仍然是:name="CheckBoxes[0].isChecked"
因此,当模型返回控制器时,列表为 null
1 我所做的其他更改是将 CheckBoxListModel.cs 从 MySite.Models.ViewModels 移动到 MySite.Areas.Reports.Models,因为其他所有内容都在 reports.models.
下好像是局部视图的问题。如果我将 @Html.EditorFor(x => x.clmReturnOptions.CheckBoxes)
放在我的主页中,则会使用全名创建复选框并正确更新。一旦我尝试在局部视图中使用 EditorFor,复选框名称就会更改,并且 link 返回到模型中断。我想在局部视图中使用它,这样我就不必在我想要复选框列表的任何地方添加所有 ui 格式。
我更新了上面的代码
创建一个接口,提供对 IList<CheckBoxModel>
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
或其他)而不是整个模型。
你应该可以开始了。
您需要将前缀传递给分部视图,以便正确命名元素
@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")