【发布时间】:2016-06-12 22:52:29
【问题描述】:
我在服务器上有一个带有 EF 6 的 ASP.Net MVC5 应用程序。该网站有十几个页面,每个页面都有一个网格,显示包含许多列的业务数据。
某些用户不会对某些页面(视图)上的某些列感兴趣,因此我需要一种方法让他们指出要使哪些视图可见。
在数据库中,一个 View 有很多 Columns,一个 User 可以指定要显示的任何视图的列(因此存储在 UserViewColumn 表中):
我正在使用以下 ViewModel 将从数据库中选择的数据传回给 View:
public class UserPrefsViewModel
{
public ICollection<VmUser> Users { get; set; }
public UserPrefsViewModel()
{
this.Users = new List<VmUser>();
}
}
public class VmUser
{
public int UserId { get; set; }
public string AdLogonDomain { get; set; }
public string AdLogonId { get; set; }
public List<VmView> Views { get; set; }
}
public class VmView
{
public int ViewId { get; set; }
public string Name { get; set; }
public List<VmColumn> AllColumns { get; set; }
public List<VmColumn> VisibleColumns { get; set; }
}
public class VmColumn
{
public int ColumnId { get; set; }
public string Heading { get; set; }
}
剃刀视图如下:
@model TVS.ESB.BamPortal.Website.Models.UserPrefsViewModel
@using System.Web.Script.Serialization
@{
ViewBag.Title = "User Preferences";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>@ViewBag.Title</h2>
@{ string data = new JavaScriptSerializer().Serialize(Model); }
<div id="ViewsAndColumns" class="container">
<div class="row">
<div id="Views" class="col-md-3 pull-left">
<span class="label-info">Views</span>
<br />
<table>
<tr>
<td>
<select style="width:100px" size="5" data-bind="options:views, optionsText: 'Name', value:selectedView"> </select>
</td>
</tr>
</table>
</div>
<div id="Columns" class="col-md-9 pull-right">
<table>
<tr>
<td>
<span class="label-info">Available Columns</span>
</td>
<td>
<span class="label-info">To Display</span>
</td>
</tr>
<tr>
<td>
<select size="10" data-bind="options:allColumns, optionsText: 'Heading', value:selectedAvailableColumn"></select>
</td>
<td>
<select size="10" data-bind="options:columnsToAdd, optionsText: 'Heading', value:selectedColumnToRemove"></select>
</td>
</tr>
<tr>
<td>
<button class="btn-default" data-bind="click:addColumn">Add</button>
</td>
<td>
<button class="btn-default" data-bind="click:removeColumn">Remove</button>
</td>
</tr>
<tr>
<td>
<button class="btn-danger" data-bind="click:saveToDatabase.bind($data, '@ViewBag.Domain', '@ViewBag.LoginId')">Save to Database</button>
</td>
</tr>
</table>
</div>
</div>
</div>
@section Scripts {
<script src="~/KnockoutVM/UserPrefs.js"></script>
<script type="text/javascript">
var vm = new ViewModel(@Html.Raw(data));
ko.applyBindings(vm, document.getElementById("UserPrefsDiv"));
</script>
}
这是一个屏幕截图:
我正在使用 knockoutjs 使用户能够将列从第一个选择列表添加到第二个,这是我的敲除文件:
function ViewModel(data) {
var self = this;
var viewColumns;
var visibleViewColumns
self.selectedAvailableColumn = ko.observable();
self.selectedView = ko.observable(data.Users[0].Views[0]);
self.views = ko.observableArray(data.Users[0].Views);
self.selectedAvailableColumn = ko.observable();
self.columnsToAdd = ko.observableArray();
self.selectedColumnToRemove = ko.observable();
var getById = function (items, id) {
return ko.utils.arrayFirst(items(), function (item) {
return item.ViewId == id;
});
};
self.allColumns = ko.computed(function () {
var view = getById(self.views, self.selectedView().ViewId);
return view ? ko.utils.arrayMap(view.AllColumns, function (item) {
return {
ColumnId: item.Id,
Heading: item.Heading
};
}) : [];
}, this);
self.addColumn = function () {
if (self.columnsToAdd().indexOf(self.selectedAvailableColumn()) < 0) {
self.columnsToAdd.push(self.selectedAvailableColumn());
}
};
self.removeColumn = function () {
self.columnsToAdd.remove(self.selectedColumnToRemove());
};
self.saveToDatabase = function () {
var jsSaveModel = ko.toJS(data);
$.ajax({
type: "POST",
url: location.href,
data: ko.toJSON(jsSaveModel),
contentType: 'application/json',
async: true
});
};
};
我的问题是,我不知道在发布到服务器之前如何最好地管理这个淘汰视图模型以使其持久保存到数据库中。如您所见,我目前将数据从服务器 VM 加载到绑定到视图控件的可观察数组中。在服务器端 VM 中,它将是 User[x].Views[y].VisibleColumns 集合,我将使用它来填充 UserViewColumn 表,标识用户希望显示的列。
我想一种方法是更改 Knockout ViewModel 接收的 data 参数。在将 data 发布到服务器之前,我可以在 self.SaveToDatabase 函数中执行此操作吗?由于我对 Knockout 或任何 MVVM 框架的经验很少,因此我将不胜感激有关最佳实践的任何建议。
【问题讨论】:
标签: mvvm knockout.js