我正在尝试弄清楚如何在我的 View 模型中使用 Knockout 映射引擎。
如果我有一个如下所示的服务器端 View 模型:
public class InventoryIndexViewModel
{
public bool IsDeleteReceiverButtonVisible { get; set; }
public IList<Receiver> Receivers { get; set; }
public string ReceiversAsJson
{
get
{
var jsonSerializerSettings = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var receivers = JsonConvert.SerializeObject(this.Receivers, jsonSerializerSettings);
return receivers;
}
}
}
Receiver 属性是一个如下所示的对象:
public class Receiver
{
public Cooperative Cooperative { get; set; }
}
Cooperative 属性是一个如下所示的对象:
public class Cooperative
{
public int Id { get; set; }
public string Name { get; set; }
}
我的观点如下:
@model InventoryIndexViewModel
@{
Layout = "~/Views/Shared/_Layout.cshtml";
ViewBag.Title = "Inventory List";
}
@section scripts{
<script>
$(function() {
var inventoryViewModel = function() {
var self = this;
self.isDeleteButtonVisible = function() { return @Model.IsDeleteReceiverButtonVisible.ToString().ToLower(); }();
self.receivers = ko.observableArray(@Html.Raw(Model.ReceiversAsJson));
};
ko.applyBindings(new inventoryViewModel());
});
</script>
}
<div class="col-md-10">
<br />
<table class="table table-striped">
<tbody data-bind="foreach: receivers">
<tr>
<td data-bind="text: serialNumber"></td>
<td data-bind="text: cooperative.Name"></td>
</tr>
</tbody>
</table>
</div>
所以问题是,如何使用复杂的 Receiver 对象。在我的 View 代码中,我尝试将数据绑定(bind)到cooperative.Name,但这不起作用。我猜测我需要使用 Knockout 映射插件,但我已经尝试过 Knockout 页面上的语法以及通过 Google 搜索找到的几种不同的语法变体,但我尝试过的似乎都不起作用。
顺便说一句,此处显示的代码与我的真实代码相比大大简化了。因此,虽然在这个简化的代码中可能有一种非常简单的方法可以通过数据绑定(bind)来获取 Cooperative.Name,但只需考虑 Receiver 对象是一个复杂的对象,它具有许多属性,这些属性本身就是复杂的对象,所以这就是Knockout 映射引擎将完成将整个对象层次结构中的所有内容都转换为可观察对象的繁重工作。
或者也许它不能,而且我离基地很远。想法?
编辑:更新了服务器端 View 模型,以正确包含我最初忘记包含的 ReceiversAsJson 方法。
最佳答案
如果您的属性在模型中定义,您可以使用映射将模型序列化为 json,如下所示:
Javascript
var data = @Html.Raw(Json.Encode(Model));
var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
查看
<table class="table table-striped">
<tbody data-bind="foreach: Receivers">
<tr>
<td data-bind="text: Cooperative.Name"></td>
</tr>
</tbody>
</table>
JsFiddle
带有示例数据的 Controller
public ActionResult Index()
{
var model = new InventoryIndexViewModel();
model.IsDeleteReceiverButtonVisible = false;
model.Receivers.Add(new Receiver { Cooperative = new Cooperative { Id = 1, Name = "aName" } });
return View(model);
}
模型
ps 我必须向集合添加一个初始化程序,即
public class InventoryIndexViewModel
{
public InventoryIndexViewModel()
{
Receivers = new List<Receiver>();
}
public bool IsDeleteReceiverButtonVisible { get; set; }
public IList<Receiver> Receivers { get; set; }
}
public class Receiver
{
public Cooperative Cooperative { get; set; }
}
public class Cooperative
{
public int Id { get; set; }
public string Name { get; set; }
}
更新
根据评论,这是一种使用映射插件与 knockout 计算函数的方法:
Javascript
var aViewModel = function(data)
{
self = this;
ko.mapping.fromJS(data, {}, self);
self.firstNameAndLastName = ko.computed(function() {
return self.FirstName() + " " + self.LastName();
});
}
var data = {"IsDeleteReceiverButtonVisible":false, "FirstName": "First", "LastName": "Last", "Receivers":[{"Cooperative":{"Id":1,"Name":"aName"}}]};
var viewModel = new aViewModel(data);
ko.applyBindings(viewModel);
HTML
<table class="table table-striped">
<tbody data-bind="foreach: Receivers">
<tr>
<td data-bind="text: Cooperative.Name"></td>
</tr>
</tbody>
</table>
<span data-bind="text:firstNameAndLastName()"></span>
jsFiddle
关于c# - 带映射插件的 knockout View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23957479/