0

我正在使用控制后代绑定的自定义绑定。这是我的代码:

HTML:

<div>
 <div data-bind="withProperties: languagesInfoViewModel()">

          <div id="languageListGrid" data-bind="kendoGrid: { data: languageViewModels, columns: [ 
                    { 
                        template: '<a href=\'\' data-bind=\'click: function() { $parent.onLanguageSelected(&quot;#=Language#&quot;) }\'>#=Language#</a>', 
                        field: 'Language', 
                        title: 'Language',
                        width: 50
                    }

                    ], 
                scrollable: false, sortable: true, pageable: false }, preventBinding: true"
        style="height: 380px"></div>


        <button data-bind="click: showLanguageDetails">Show Language Details</button>
    <div class="hidden" data-bind="withProperties: selectedLanguageViewModel()">
              <form id="languageDetailsForm" action=" ">

                  <div data-bind="kendoWindow: {isOpen: isOpenPopUp, title:'Language', width: 400, height: 200, modal: true }">
                            test
                            <button id="cancelLanguage" class="k-button" data-bind="click: cancelLanguage">Cancel</button>
                  </div>
              </form>
    </div>
 </div>

Javascript

$(function () {
ko.bindingHandlers.preventBinding = {
    init: function () {
        return {
            controlsDescendantBindings: true
        };
    }
};

ko.bindingHandlers.withProperties = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

        var childViewModel = valueAccessor();

        childViewModel.isOpen.subscribe(function (isOpen) {
            if (isOpen) {
                var innerBindingContext = bindingContext.extend(childViewModel);
                ko.applyBindingsToDescendants(innerBindingContext, element);
            };
        });

        return { controlsDescendantBindings: true };
    }
};

ko.bindingHandlers.kendoGrid.options.dataBound = function (data) {
    var body = this.element.find("tbody")[0];

    if (body) {
        ko.applyBindings(ko.dataFor(body), body);
    }
};

var FranchiseInitializer = function () {

    var self = this;

    var initialize = function () {
        var franchiseDetailsViewModel = new FranchiseDetailsViewModel();
        ko.applyBindings(franchiseDetailsViewModel);
        franchiseDetailsViewModel.open();
    };

    initialize();
};

var FranchiseDetailsViewModel = function () {

    var self = this;

    var initialize = function () {
        self.languagesInfoViewModel(new LanguageListViewModel(self));
    };

    self.languagesInfoViewModel = ko.observable();

    self.open = function () {
        self.isOpen(true);
        self.languagesInfoViewModel().open();
    };
    self.isOpen = ko.observable(false);


    initialize();
};

var LanguageListViewModel = function (franchise) {

    var self = this;

    var initialize = function () {
        var languageViewModel = new LanguageDetailsViewModel('English', franchise);
        self.languageViewModels.push(languageViewModel);
        var languageViewModel1 = new LanguageDetailsViewModel('Spanish', franchise);
        self.languageViewModels.push(languageViewModel1);
        self.selectedLanguageViewModel(languageViewModel);
    };

    self.languageViewModels = ko.observableArray([]);
    self.selectedLanguageViewModel = ko.observable();

    self.open = function () {
        self.isOpen(true);
    };
    self.isOpen = ko.observable(false);

    self.showLanguageDetails = function () {
        self.onLanguageSelected("English");
    };

    var getLanguageViewModel = function (language) {
        return self.languageViewModels().filter(
            function (element, index, array) {
                return (element.Language() == language);
            })[0];
    };

    self.onLanguageSelected = function (selectedLanguage) {
        var languageViewModel = getLanguageViewModel(selectedLanguage);
        self.selectedLanguageViewModel(languageViewModel);
        self.selectedLanguageViewModel().open();
    };

    initialize();
};

var LanguageDetailsViewModel = function (lang, franchise) {
    var self = this;

    var closePopUp = function () {
        self.isOpen(false);
        self.isOpenPopUp(false);
    };

    self.isOpenPopUp = ko.observable(false);
    self.Language = ko.observable(lang);

    self.open = function () {
        self.isOpen(true);
        self.isOpenPopUp(true);
    };
    self.isOpen = ko.observable(false);

    self.cancelLanguage = function () {
        closePopUp();
    };
};

var initialize = new FranchiseInitializer();

我有以下问题:

当我从网格中选择一种语言时,onLanguageSelected应该执行一个函数。但我收到一个错误'onLanguageSelected' is undefined。我对其进行调试,似乎在单击网格时,我处于父上下文中FranchiseDetailsViewModel,而不是 LanguageListViewModel. 我无法在模板中说出类似 $child.onLanguageSelected 的内容。我怎样才能解决这个问题?

小提琴

http://jsfiddle.net/2Qnv7/16/

还有一些奇怪的事情:当您单击Show language details按钮时,应该会打开一个弹出窗口,但只显示动画并冻结。奇怪的是它在我的 asp.net mvc 4 应用程序中完美运行。有什么想法吗?

更新:

我能够做这样的工作:

languagesInfoViewModel().onLanguageSelected(&quot;#=Language#&quot;)

但我不太喜欢模板中的这段代码。也许有更灵活的解决方案?

4

1 回答 1

1

基于“dataBound”处理程序,整个网格的上下文是您的FranchiseDetailsViewModel.

您必须按照您的建议将其称为:languagesInfoViewModel().onLanguageSelected(&quot;#=Language#&quot;)

或者您可以考虑尝试使用 Knockout-Kendo 现在支持的行级 KO 模板。

于 2013-01-25T16:27:15.353 回答