向 ViewModel 添加动态添加的控件
Adding dynamically added controls to the ViewModel
我有以下 ViewModel,其中填充了一些预定义的数据。其中一个预定义数据是 ApplicationParameter ViewModel 列表,它设置为最初显示 n 个 ApplicationParameters。
我想要实现的是允许用户在单击按钮时添加额外数量的 ApplicationParameters ViewModel,这是我通过使用 ApplicationParameter 代码调用 PartialView 实现的。正如预期的那样,控件会自动添加,但它们在 ViewModel 中无法识别,因为它们没有正确的命名(因为它们是嵌套的)。
如何使动态添加的控件对 POST 上返回的 ViewModel 可见。
视图模型
public class ApplicationVM
{
public int idApplication { get; set; }
public int idCompany { get; set; }
public string Company { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Link { get; set; }
public string Photo { get; set; }
public List<ApplicationParameterVM> ApplicationParameters { get; set; }
}
public class ApplicationParameterVM
{
public string Name { get; set; }
public bool Keep { get; set; }
}
操作视图(代码段)
<tbody id="editorRows">
@for (int i = 0; i < Model.ApplicationParameters.Count(); i++)
{
<tr>
<td>
@Html.TextBoxFor(m => Model.ApplicationParameters[i].Name, new { @class = "form-control" })
@Html.CheckBoxFor(m => Model.ApplicationParameters[i].Keep)
</td>
</tr>
}
</tbody>
用于添加 ApplicationParameterVM 的操作视图
@model AccessMarketmind.Areas.Administration.ViewModels.ApplicationParameterVM
@{
Layout = null;
}
<tr class="application-parameters">
<td>
@Html.TextBoxFor(m => Model.Name, new { @class = "form-control" })
@Html.CheckBoxFor(m => Model.Keep)
</td>
</tr>
我知道这看起来微不足道,可以使用 Javascript 轻松完成,但问题是我有更复杂的 ViewModel(阅读:大量嵌套),其中 Javascript 不是选项。
此类动态表单的基本技巧是发布的表单数据应与 属性 名称相匹配。
例如:动态控件数组的最终 属性 名称应该是。
ApplicationParameters[0].Name 和 ApplicationParameters[0].Keep
和
ApplicationParameters[1].Name 和 ApplicationParameters[1].Keep
.....
要实现这一点,请仅使用松散耦合的助手 Html.TextBox()。
在得到有用的答案后,我能够让这件事完全按照我想要的方式工作。我所做的是服务器端和客户端代码的组合,我的想法是基本上将额外的 属性 添加到我命名为 ControlName 且类型为字符串的 ViewModel 中。这样做的好处是,如果您的 ViewModel 发生变化,您可以轻松地根据当前需求调整代码而无需太多麻烦,更不用说您只需将 ControlName 属性 添加到每个ViewModel 子级别。
注意:以下示例不是 OP
中提到的示例
首先,您需要某种包装器(在我的例子中是 table)和一个 link,它将允许您创建新的控件行:
@Html.ActionLink("Add attribute", "AddProductCategoryAttribute", null, new { id = "addProductCategoryAttribute" })
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>
</th>
<th>
Attribute
</th>
<th>
Measure
</th>
</tr>
</thead>
<tbody id="productCategoryAttributes"></tbody>
</table>
在客户端你需要这样的东西
<script type="text/javascript">
$("#addProductCategoryAttribute").click(function () {
elementCount = $(".productCategoryAttribute").length;
$.ajax({
url: this.href + "?elementCount=" + elementCount,
cache: false,
success: function (html) {
$("#productCategoryAttributes").append(html);
}
});
return false;
})
</script>
请注意附加到 link 的 elementCount - 此查询字符串用于让 Action 方法知道有多少元素已经存在。说到Action方法,现在是这个样子
public ActionResult AddProductCategoryAttribute(int elementCount)
{
ProductCategoryOverview.ProductCategoryAttributeVM productCategoryAttributeVM = new ProductCategoryOverview.ProductCategoryAttributeVM();
productCategoryAttributeVM.ControlName = "ChangeThisNameToWhateverIsNeeded[" + elementCount.ToString() + "].";
productCategoryAttributeVM.Keep = true;
return View(productCategoryAttributeVM);
}
我有以下 ViewModel,其中填充了一些预定义的数据。其中一个预定义数据是 ApplicationParameter ViewModel 列表,它设置为最初显示 n 个 ApplicationParameters。
我想要实现的是允许用户在单击按钮时添加额外数量的 ApplicationParameters ViewModel,这是我通过使用 ApplicationParameter 代码调用 PartialView 实现的。正如预期的那样,控件会自动添加,但它们在 ViewModel 中无法识别,因为它们没有正确的命名(因为它们是嵌套的)。
如何使动态添加的控件对 POST 上返回的 ViewModel 可见。
视图模型
public class ApplicationVM
{
public int idApplication { get; set; }
public int idCompany { get; set; }
public string Company { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Link { get; set; }
public string Photo { get; set; }
public List<ApplicationParameterVM> ApplicationParameters { get; set; }
}
public class ApplicationParameterVM
{
public string Name { get; set; }
public bool Keep { get; set; }
}
操作视图(代码段)
<tbody id="editorRows">
@for (int i = 0; i < Model.ApplicationParameters.Count(); i++)
{
<tr>
<td>
@Html.TextBoxFor(m => Model.ApplicationParameters[i].Name, new { @class = "form-control" })
@Html.CheckBoxFor(m => Model.ApplicationParameters[i].Keep)
</td>
</tr>
}
</tbody>
用于添加 ApplicationParameterVM 的操作视图
@model AccessMarketmind.Areas.Administration.ViewModels.ApplicationParameterVM
@{
Layout = null;
}
<tr class="application-parameters">
<td>
@Html.TextBoxFor(m => Model.Name, new { @class = "form-control" })
@Html.CheckBoxFor(m => Model.Keep)
</td>
</tr>
我知道这看起来微不足道,可以使用 Javascript 轻松完成,但问题是我有更复杂的 ViewModel(阅读:大量嵌套),其中 Javascript 不是选项。
此类动态表单的基本技巧是发布的表单数据应与 属性 名称相匹配。
例如:动态控件数组的最终 属性 名称应该是。
ApplicationParameters[0].Name 和 ApplicationParameters[0].Keep
和
ApplicationParameters[1].Name 和 ApplicationParameters[1].Keep
.....
要实现这一点,请仅使用松散耦合的助手 Html.TextBox()。
在得到有用的答案后,我能够让这件事完全按照我想要的方式工作。我所做的是服务器端和客户端代码的组合,我的想法是基本上将额外的 属性 添加到我命名为 ControlName 且类型为字符串的 ViewModel 中。这样做的好处是,如果您的 ViewModel 发生变化,您可以轻松地根据当前需求调整代码而无需太多麻烦,更不用说您只需将 ControlName 属性 添加到每个ViewModel 子级别。
注意:以下示例不是 OP
中提到的示例首先,您需要某种包装器(在我的例子中是 table)和一个 link,它将允许您创建新的控件行:
@Html.ActionLink("Add attribute", "AddProductCategoryAttribute", null, new { id = "addProductCategoryAttribute" })
<table class="table table-condensed table-striped">
<thead>
<tr>
<th>
</th>
<th>
Attribute
</th>
<th>
Measure
</th>
</tr>
</thead>
<tbody id="productCategoryAttributes"></tbody>
</table>
在客户端你需要这样的东西
<script type="text/javascript">
$("#addProductCategoryAttribute").click(function () {
elementCount = $(".productCategoryAttribute").length;
$.ajax({
url: this.href + "?elementCount=" + elementCount,
cache: false,
success: function (html) {
$("#productCategoryAttributes").append(html);
}
});
return false;
})
</script>
请注意附加到 link 的 elementCount - 此查询字符串用于让 Action 方法知道有多少元素已经存在。说到Action方法,现在是这个样子
public ActionResult AddProductCategoryAttribute(int elementCount)
{
ProductCategoryOverview.ProductCategoryAttributeVM productCategoryAttributeVM = new ProductCategoryOverview.ProductCategoryAttributeVM();
productCategoryAttributeVM.ControlName = "ChangeThisNameToWhateverIsNeeded[" + elementCount.ToString() + "].";
productCategoryAttributeVM.Keep = true;
return View(productCategoryAttributeVM);
}