使用JavaScript和MVC / Razor将Kendo控件绑定到HtmlHelper控件

Binding a Kendo control to an HtmlHelper control using JavaScript and MVC / Razor

本文关键字:控件 Kendo 绑定 HtmlHelper Razor JavaScript MVC 使用      更新时间:2023-09-26

我有一个MVC ListBoxFor控件,我试图绑定数据,并使用Kendo MultiSelectFor更新。

这个想法是在ListBox中有一个用户列表,在MultiSelect框中有一个可用用户列表。当从MultiSelect框中选择用户并单击add按钮时,将对更新用户列表的操作进行Ajax调用(通过各种API调用,这些调用都可以正常工作),并使用客户端JavaScript更新用户和可用用户数组对象,并且绑定使控件与更新的列表保持最新状态。

我希望我能把这个问题归结为一个问题,但老实说,每次我尝试一些东西时,我都会出现不同的错误,所以我就用最新的迭代。

模型:

public IEnumerable<UserInformation> Users { get; set; }
public IEnumerable<UserInformation> AvailableUsers { get; set; }
JavaScript ViewModel:

var viewModel = kendo.observable({
        availableUsersSelected: [],
        users: @(Html.Raw(Json.Encode(this.Model.Users))),
        availableUsers: @(Html.Raw(JsonConvert.SerializeObject(this.Model.AvailableUsers))),
        moveToUsers: function () {
            this.availableUsersSelected = this.get('availableUsersSelected');
            this.users.push(this.availableUsers);
            if (this.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: this.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            this.users.remove(this.availableUsersSelected);
                        }
                    }
                });
            }
        }
    });

MultiSelectFor控制

@(Html.Kendo()
    .MultiSelectFor(u => u.AvailableUsers)
    .Placeholder("Please select")
    .BindTo(new SelectList(Model.AvailableUsers, "Id", "Name"))
    .HtmlAttributes(new { data_bind = "value: availableUsersSelected" })
)
ListBox控件

@(Html.EditorLine(Language.Fields.Users, Html.ListBoxFor(u => u.Users, new SelectList(Model.Users, "Id", "Name"), new { @class = "form-control", data_bind = "source: users", data_value_field ="Id", data_text_field = "Name" })))

添加控制

<img src="~/Content/images/up-arrow.jpg" alt="Move to users" width="30" data-bind="events: {click: moveToUsers}" />

重申一下,Ajax调用和更新服务器端都工作得很好,我很难理解的是客户端控件绑定。

我得到的错误是1)语法错误,这行users: @(Html.Raw(Json.Encode(this.Model.Users))),和它之后的行(同样的事情,有效),以及2)当添加按钮按下时,moveToUsers函数调用上的"ReferenceError: Id未定义"。

(我可以诚实地说,我在这个问题上所经历的挫败感让我发疯,所以如果它出现在问题中,我很抱歉)

所以在平静下来之后,阅读了一些关于数据绑定和可观察数组的文档,我意识到我犯了一些基本的错误。

JavaScript ViewModel:

var viewModel = {
        availableUsersSelected: new kendo.data.ObservableArray([]),
        users: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.Users)))),
        availableUsers: new kendo.data.ObservableArray(@(Html.Raw(Json.Encode(this.Model.AvailableUsers)))),
        moveToUsers: function () {
            if (viewModel.availableUsersSelected.length > 0) {
                var formAction = '@Url.Combine(Url.Content("~/"), ControllerActions.Groups.GroupDefault, ControllerActions.Groups.AddUser)';
                $.ajax({
                    url: formAction,
                    type: 'POST',
                    data: {
                        model: JSON.stringify(
                            {
                                groupId: $('#GroupId').val(),
                                users: viewModel.availableUsersSelected
                            }
                    )
                    },
                    success: function (result) {
                        if (result) {
                            removeFromAvailableUsers();
                        }
                        else
                            alert('add failed!');
                    },
                    failure: function () {
                        alert('ajax failed!');
                    }
                });
            }
        }
    };
function removeFromAvailableUsers() {
    for (var i = 0; i < viewModel.availableUsersSelected.length; ++i) {
        viewModel.users.push(viewModel.availableUsersSelected[i]);
        viewModel.availableUsers.remove(viewModel.availableUsersSelected[i]);
    }
    var ele = $('#AvailableUsers').data("kendoMultiSelect");
    ele.value("");
    ele.input.blur();
};

主要的区别在于,不是将整个对象声明为一个kendo可观察对象,而是将每个数组声明为一个可观察数组,然后通过viewModel对象引用它们,而不是假设"this"作用域将封装它们。

然后,正如D_Learning在上面的评论中提到的,我不必要地为MultiSelect控件使用了两个绑定,所以它变成了:
    @(Html.Kendo()
        .MultiSelectFor(u => u.AvailableUsers)
        .Placeholder("Please select")
        .HtmlAttributes(new { data_bind = "source: availableUsers, value: availableUsersSelected", data_value_field = "Id", data_text_field = "Name" })
    )

(注意没有"。BindTo"属性)

除此之外,MVC方面的东西保持不变,并且都很完美。

如果您希望删除或添加数据到Kendo Multiselect,那么您需要通过DataSource添加它们:

$("#AvailableUsers").data("kendoMultiSelect").dataSource.add({"text": "new Item", "value": 1000});

有关在Multiselect(剑道数据源)中添加或删除项目的更多详细信息,请参见:剑道数据源添加删除项目

同样,您可以从列表框中删除项目,如下所示:

        var selectedIndex = ListBox1.selectedIndex();
        clearSelection();
        if (selectedIndex != -1) {
            ListBox1.options.remove(selectedIndex);

有关从HTML列表框中添加或删除项的更多详细信息,请参见:HTML列表框项操作。