ASP.NET MVC嵌套视图模型和Knockout

6

我无法理解如何在 ASP.NET MVC 4 的嵌套视图模型中实现 knockout :

public class MyProfile
{
  public string Name { get; set; }

  public IList<VM1>   List1    { get; set; }
  public IList<VM2>   List2    { get; set; }
  ....
  public IList<VM10>  List10    { get; set; }
}
// example of VM view model
public class VM1
{
   IList<Label> Labels { get; set; }
   IList<Contact1> Contact1 { get; set; }
}

在我看来,我接受这样的模型:

@model MyProfile

@using (Html.BeginForm("Index", "Profile", FormMethod.Post, new { id = "profileEditorForm" }))
{

  @Html.ValidationSummary(false)
    <fieldset>
  <legend>User's data</legend>
  <label for="name">Name:</label>
  <input type="text" id="name" name="name" class="required" data-bind="value: Name"/>
    </fieldset>

 @Html.EditorFor(m => @Model.List1, "List1") @* Editpr model for List1*@
 @Html.EditorFor(m => @Model.List2, "List2")
 .....
 @Html.EditorFor(m => @Model.List10, "List10")

 <p>
   <input type="submit" value="Save" data-bind="enable: (List1().length > 0) && (List2().length > 0) && ...(List10().length > 0)" />
<a href="/">Cancel</a>
 </p>
}

如果有多个问题,List1 的编辑模板将如下所示:

@model IList<FiveW.ViewModels.List1>

<fieldset>

  <table>
    <tbody data-bind="foreach: Contact1">
      <tr>
        <td>
          <label>Email:</label></td>
        <td>
          @* How do you put combobox here with labels here?
          How do you tie selected label to selected property on your Contact1 object *@
          @*<select data-bind="options: Labels, optionsText: 'LabelName', value: selectedLabel, optionsCaption: 'Choose...'"></select></td>
        <td>
          <input type="text" data-bind="value: Name, uniqueName: true" class="required" /></td>
        <td>
          <a href="#" data-bind="click: function() { viewModel.removeContact1(this); }">Delete</a></td>
      </tr>
    </tbody>
  </table>


  <button data-bind="click: addContact1">Add Contact1</button>

</fieldset>

编辑

VM1到VM10除了验证逻辑外都是相同的,因此我必须将它们作为不同的类(不幸的是,在模型和视图中存在大量重复)。

客户端 - 这就是我要问的内容: 我需要从ASP MVC模型传递包含嵌套列表的数据,并在客户端使用knockout呈现它们(我发现它在处理动态列表方面做得最好)。 这类似于gmail联系人 - 您有家庭/工作/移动/传真电话 - 因此一个列表是电话的标签(是哪个电话),应该作为下拉框呈现,另一个是可变长度的电话动态列表,可以根据用户点击增加。

结束编辑

  1. 我不明白如何从这个嵌套模型创建knockout viewModel,显然名称应该是其中的一部分,但其余部分都是列表,它们还包含列表。

  2. 如何进行映射?

  3. 如何处理它(一个进入下拉列表,将成为另一个列表的标签,后者的长度是可变的 - 这里唯一使用knockout的原因)?

  4. 填写完毕后,如何将它们全部组合在一起并发送回控制器操作?

  5. 当标签是下拉列表(或组合框)时,如何编写编辑器模型(示例为:[label]home/work [name]email,[label]mobile/home/car [name]phone)

如果它是带有IList的简单类 - 就像这里一样。问题是列表中还有列表,Knockout要求所有内容都是可观察的,不确定如何在JavaScript中表达此嵌套模型。

请帮忙。谢谢!


每个列表元素都是不同的类型吗?我看到您已声明了VM1,是否还会有VM2、VM3、VM…n作为类声明?它们是不同的还是可以创建一个通用类列表类型并只有10个实例? - amhed
请参见编辑。VM1除了数据注释(或在流畅验证的情况下为验证规则)外,与VM2相同。我想问的是客户端。两个列表 - 一个是另一个(电话/电子邮件/地址等)的组合框(工作/家庭)。如何在Knockout中表达它...谢谢。 - Display Name
如果类相同(属性名称和类型一致),那么您只需要一个子ViewModel。我会写一个例子并尝试回答这五个问题。 - amhed
非常感谢,这为我澄清了一些事情,但我的最大担忧仍未解决 - 如何将ComboBox放置在编辑器模板中,以便可以选择并将其发送回服务器,以表明“Contact1”是“Label2”类型的,例如标签可以在编辑器模板中选择。谢谢! - Display Name
你需要找到一种方法将htmlattribute传递给编辑器模板,以便它具有类似于data-bind="List1.Labels[0].Property"的绑定。 - amhed
显示剩余3条评论
2个回答

0

不得不重新修改问题,以单独确定我遇到的问题,而不是像这里一样提出普通问题。

非常感谢你们的回答,但遗憾的是,如果你没有正确表达你的问题,你会得到相应的常见(非特定)回复。所以这是我的错。

由于有很多人对我提出的问题感兴趣(前3个小时内就有5个赞),这里是我提出了相同的问题,并强调了我遇到的具体问题,找到了正确的答案并解决了我的难题。

ASP.NET中使用Knockout可变长度列表和ComboBox - 如何绑定?

希望这能帮助到需要的人,就像它帮助了我一样,再次感谢!


0

我不会使用映射。我会在客户端直接声明ViewModel,就像这样:

//I'm asuming the properties for Label and Contact, this is just for example purposes
function LabelViewModel(){
    var self = this;
    self.LabelName = ko.observable();
}
function Contact(){
    var self = this;
    self.Name = ko.observable();
    self.LastName = ko.observable();
}

//This is the definition for the List. I believe it shouldn't matter that the class names are different as long as the structure is the same
function ListViewModel(){
    var self = this;
    self.Labels = ko.observableArray();
    self.Contacts = ko.observableArray();
}

function MainViewModel(){
    var self = this;
    self.Name = ko.observable();
    self.List1 = ko.observableArray();
    //....
    self.List10 = ko.observableArray();
}


$(document).ready(function(){
    var viewModel = new MainViewModel(@Html.Raw(JsonConvert.SerializeObject(Model)));
    ko.applyBindings(viewModel);
});

然后,当提交时,我会尝试从 jQuery 中进行提交,而不是直接进行 HTTP POST:

var viewModelJs = ko.toJS(ko.utils.unwrapObservable(viewModel));
var parameters = JSON.stringify({vm: viewModelJs});

$.ajax('http://yourControllerUrlHere', {
    data: parameters,
    type: "POST",
    contentType: "application/json",
    dataType: "json",
    success: function (result) {
        console.log('Submitted ok');
    },
    error: function (error) {
        console.log(error);
    }
});

除了主模型之外,我主要关注我使用的EditorTemplates:List1到List10。它们的作用在于附加编辑 - 基本上显示下拉列表(最好是组合框),其中标签作为选择选项,主输入文本作为联系人#。例如,我使用了gmail联系人信息:Contact1是电子邮件,其标签可以在“工作”,“家庭”或“自定义”中选择... - 如何表达组合框以及其内容(email@domain.com被标记为“家庭”电子邮件)- 希望你能理解。假设所有属性都是字符串。请参见附加编辑 - 我添加了EditorTemplate。谢谢! - Display Name
你在数据绑定中使用了'value: Name, uniqueName: true'。你需要传递整个路径,这就是为什么我告诉你要寻找一种从主视图传递HtmlAttributes对象的方法。而不是'value: Name',应该是类似于'List1()[0].PropertyYouNeedToAccess'的东西。 - amhed
这里有一个类似的答案,解决了嵌套绑定问题:http://stackoverflow.com/questions/7466423/dynamic-data-binding-to-nested-properties-in-knockout-js-with-dialog-asp-net - amhed

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接