【发布时间】:2012-02-27 20:15:27
【问题描述】:
我正在尝试使用 knockout.js 获得四个级联下拉列表:
- 搜索条件
- 子标准
- 价值
- 状态
通过使用以下链接中的代码,我能够启动第一个级联(但由于数据绑定问题而无法启动其他级联):
http://blogs.msdn.com/b/thebeebs/archive/2011/12/01/price-calculator.aspx
这些下拉列表的数据将作为 SearchCriterion 的 IEnumrable 从使用 ViewBag.CriteriaData 变量的 MVC 视图返回到我的 razor 视图页面。我的类的代码如下:
public class SearchCriterion
{
public string Text { get; set; }
public string Value { get; set; }
public List<SubCriterion> SubCriteria { get; set; }
}
public class SubCriterion
{
public string SearchCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public List<ColumnValue> ColumnValues { get; set; }
}
public class ColumnValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string Text { get; set; }
public string Value { get; set; }
public IEnumerable<StateValue> StateValues { get; set; }
}
public class StateValue
{
public string SearchCriterionValue { get; set; }
public string SubCriterionValue { get; set; }
public string ColumnValue { get; set; }
public IEnumerable<int> InputStateIds { get; set; }
public IEnumerable<int> OutputStateIds { get; set; }
public int SelectedInputStateId { get; set; }
public int SelectedOutputStateId { get; set; }
public string Text { get; set; }
public string Value { get; set; }
}
我面临的问题在于 .cshtml 代码的以下部分:
-
我在此模板中为其他两个下拉菜单指定什么。例如第三个下拉菜单需要绑定到 ColumnValue.Value(ColumnValue 是 SubCriterion 的一部分)
<script id='criteriaRowTemplate' type='text/html'> <tr> <td><select data-bind='options: criteriaData, optionsText: "Text", optionsCaption: "Search Criterion", value: SearchCriterion' /></td> <td><select data-bind='visible: SearchCriterion, options: SearchCriterion() ? SearchCriterion().SubCriteria : null, optionsText: "Text", optionsCaption: "Sub Criterion", value: SubCriterion' /></td> <td><select data-bind='visible: SubCriterion, options: SubCriterion() ? SubCriterion().ColumnValues : null, optionsText: "Text", optionsCaption: "Column Value", value: ColumnValue'/></td> <td><select data-bind='visible: ColumnValue, options: ColumnValue() ? ColumnValue().StateValues : null, optionsText: "Text", optionsCaption: "State", value: StateValue'/></td> <td><button data-bind='click: function() { viewModel.removeLine($data) }'>Remove</button></td> </tr> </script> -
这是正确的吗?
var CriteriaLine = function() { this.SearchCriterion = ko.observable(); this.SubCriterion = ko.observable(); this.ColumnValue = ko.observable(); this.StateValue = ko.observable(); // Whenever the Search Criteria changes, reset the Sub Criteria selection this.SearchCriterion.subscribe(function() { this.SubCriterion(undefined); }.bind(this)); this.SubCriterion.subscribe(function() { this.ColumnValue(undefined); }.bind(this)); this.ColumnValue.subscribe(function() { this.StateValue(undefined); }.bind(this));};
-
如何将完整的 C# 对象与 Javascript 对象映射?如果我们只有前两个下拉菜单,它就可以工作:
// Create a Javascript object object with the same property names as the C# object var dataToSearch = $.map(this.lines(), function (line) { return line.StateValue() ? line.StateValue() : undefined; }); var SearchObject = new function () { this.StateValues = dataToSearch; }; // Convert the object to JSON var searchCriteria = JSON.stringify(SearchObject); -
这里有什么需要更改的绑定吗?
// Apply the data from the server to the variable var criteriaData = @Html.Raw(@Json.Encode(ViewBag.CriteriaData)); var viewModel = new Criteria(); ko.applyBindings(viewModel, document.getElementById("criteriaDiv"));
编辑:
我现在可以填充级联下拉列表(上面更新了代码)。现在我有 4 列,每列都有一个下拉列表。我还使用 Knockoutjs 动态添加了 1...n 行。因此,用户现在可以从这些下拉列表中选择值,并根据需要添加更多行下拉列表。剩下的唯一事情是将用户为下拉菜单选择的值返回给控制器(上面的第 3 点)。我不确定我该怎么做。任何帮助,将不胜感激。
编辑 2:
为 Item #3 添加了工作代码并修改了 ColumnValue 和 StateValue 类。
【问题讨论】:
-
您的实现看起来很吓人,因为您有 4 个单独的下拉菜单,其中每个子下拉菜单取决于父项的值(即子条件取决于条件的值)。因此,假设您有 10 个不同的标准,对于每个标准,它们可以有 10 个子标准,以及这 10 个值中的每一个,以及这 10 列中的每一个。那是 10 + 10^2 + 10^3 + 10^4 值,或可能的 11,110 种组合。相反,您应该摆脱 List 集合,并让每个下拉列表触发 AJAX 请求以填充子下拉列表。
-
如果我有这么多病例,我也会害怕。但是这里的下拉菜单不仅取决于父母,还取决于他们的祖父母。所以选项的总数是相当有限的。搜索条件下拉列表将只有 6 个值,子条件最多 2-4 个值,值下拉列表将主要有 2-3 个值,但在某些情况下可能有 10 个左右的值,最后一个下拉列表将只有 2 个值。我将所有这些作为基于我的缓存的嵌套对象传递回来,没有任何性能滞后。所以,如果 seomeone 可以帮助我使用绑定语法,我不介意发送所有数据。
-
好的,据我所知,您正在将 C# 数据正确地分解为 JavaScript 对象。我使用 $.json.decode(someObject) (jQuery插件),但它是一回事。至于订阅和数据更改,我会采用我在下面建议的方式,您实际上是绑定到计算值的。然后您可以简化您的 ViewModel,而不是试图自己跟踪所有内容。
-
这里有一篇非常简单的关于JSON序列化和反序列化的文章。就我个人而言,我对所有数据传输对象都使用 WCF 样式,然后我就让 .net 发挥作用。它与这个例子几乎相同......但希望这会让你开始。 blogs.msdn.com/b/rakkimk/archive/2009/01/30/…
标签: asp.net-mvc-3 data-binding knockout.js cascadingdropdown