无法使用knockout绑定viewmodel

时间:2013-03-10 05:51:10

标签: asp.net knockout.js

我正在尝试使用knockout.js将对象轻松绑定到视图;然而, 我已经到了一个我不明白发生了什么的地步...... 出于某种原因,我的观点没有受到约束。在我的页面上,我有一个包含产品类别列表的下拉列表。更改类别后,我想使用属于所选类别的产品信息填充html表。

以下是我正在使用的代码。

HTML:

    <asp:DropDownList ID="ddlProductCategory" runat="server" ClientIDMode="Static">
    </asp:DropDownList>
    <div id="divProducts">
        <table width='100%' border="1">
        <thead>
            <tr>
                <th width='25%'>
                    Product ID
                </th>
                <th width='25%'>
                    Product Name
                </th>
                <th width='15%'>
                    Supplier ID
                </th>
                <th width='10%'>
                    Category ID
                </th>
                <th>
                    QuantityPerUnit
                </th>
                <th>
                    UnitPrice                    
                </th>
                <th>
                     UnitsInStock
                </th>
                <th>
                     UnitsOnOrder
                </th>                    
            </tr>
        </thead>
        <tbody data-bind="foreach: Products">
           <tr>
                <td>
                    <span data-bind="text: ProductID"> </span>
                </td>
                <td>
                    <span data-bind="text: ProductName"> </span>
                </td>
                <td>
                    <span data-bind="text: SupplierID"> </span>
                </td>
                <td>
                    <span data-bind="text: CategoryID"> </span>
                </td>
                <td>
                    <span data-bind="text: QuantityPerUnit"> </span>
                </td>
                <td>
                    <span data-bind="text: UnitPrice"> </span>
                </td>
                <td>
                    <span data-bind="text: UnitsInStock"> </span>
                </td>
                <td>
                    <span data-bind="text: UnitsOnOrder"> </span>
                </td>
                <td>
                    <a href='#' data-bind='click: $parent.removeLine'>Remove</a>
                </td>
            </tr>
        </tbody>
    </table>
    </div>

在服务器.NET JavaScriptSerializer对象上获取json表示 产品对象列表:

[WebMethod(EnableSession = true)]
[System.Web.Script.Services.ScriptMethod(ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)]
public object ProcessRequest(string oData)
{
    // Some code to get listOfProducts
    var json = new JavaScriptSerializer().Serialize(listOfProducts);
    return json;
}

这是我的ViewModel对象:

function ProductsListViewModel (bindingData) {
    var self = this;  

    this.Products = {};

    //////////////////////////////////////////////
    // Load
    /////////////////////////////////////////////
    this.BindViewModel = function (jsonProducts) {
        var _bindingData = jsonProducts;

        if (_bindingData && ObjectTypeChecker.IsJsonObject(_bindingData)) {
            _bindingData = $.parseJSON(_bindingData);
        }

        if (_bindingData && _bindingData.d) {
            _bindingData = eval(_bindingData.d);
        }

        self.Products = _bindingData;
        ko.mapping.fromJS(self.Products, self);
    };

    this.InitialLoad = function()
    {
        var _bindingData = bindingData;

        if (_bindingData && ObjectTypeChecker.IsJsonObject(_bindingData)) {
            _bindingData = $.parseJSON(_bindingData);
        }

        if (_bindingData && _bindingData.d) {
            _bindingData = eval(_bindingData.d);
        }

        self.Products = _bindingData;

        ko.mapping.fromJS(self.Products, {});
    }

    this.InitialLoad();

    ////////////////// STATIC METHODS ////////////////////////////
    ProductsListViewModel.GetCurrentModel = function () {
        return self;
    }
};

在客户端,在第一次加载时,我正在使用空值初始化我的viewmodel,从服务器获取对象的“元数据”,这完全正常:

$(document).ready(function () {

    // Call server for metadata
    var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler",   "GetMetadata", ["Products"]);
    var jsonProducts = agent.GetMetadata();

    // Now Load initial state for viewmodel
    LoadModels();
});


// Load metadata for all viewmodels
function LoadModels() {
    var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler",  "GetMetadata", ["Products"]);
    var jsonProducts = agent.GetMetadata();

    // Load ProductListViewModel //////////////////////////////////
    myProductsViewModel = new ProductsListViewModel(jsonProducts);
    ko.applyBindings(myProductsViewModel);
    ///////////////////////////////////////////////////////////////

}

之后每当下拉列表中的值发生变化时,我都会调用JQuery.ajax方法来获取产品信息,我试图将返回的数据绑定到View:

 // Event Handler for Categories Drpdown
 function onCategoryChange(event) {
    // get data
    var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler",  event.type, event.eventArgs);
    var jsonProducts = agent.GetProductsByCategory(event.eventArgs);

    // jsonProducts is a list of products in json format:
    // {"d":"  [{\"ProductID\":1,\"ProductName\":\"Chai\",\"SupplierID\":1,\"CategoryID \":1,\"QuantityPerU nit\":\"10 boxes x 20 bags\",\"UnitPrice\":18.0000,\"UnitsInStock\":39,\"UnitsOnOrder\":0},
//        {\"ProductID\":2,\"ProductName\":\"Chang\",\"SupplierID\":1,\"CategoryID\":1,\"QuantityPerUnit\":\"24 - 12 oz bottles\",\"UnitPrice\":19.0000,\"UnitsInStock\":17,\"UnitsOnOrder\":40}]"}

    // Re-bind view
    BindView(jsonProducts);
}


function BindView(jsonProducts) {
    ProductsListViewModel.GetCurrentModel().BindViewModel(jsonProducts);
}

请帮助!


这是我上一篇文章的更新。我发现以下工作正常:

var myProductsViewModel = null;

$(document).ready(function () {
    // Load all models
    LoadModels();
});

function onCategoryChange(event) {
     var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler", event.type, event.eventArgs);
     var jsonProducts = agent.GetProductsByCategory(event.eventArgs);
     BindView(jsonProducts);
}


function LoadModels() {
     var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler", "GetMetadata", ["Products"]);
     var jsonProducts = agent.GetMetadata();

     // Load ProductListViewModel //////////////////////////////////
     ///////////////////////////////////////////////////////////////
     if (jsonProducts && ObjectTypeChecker.IsJsonObject(jsonProducts)) {
        bbbData = $.parseJSON(jsonProducts);
     }

     if (bbbData && bbbData.d) {
         list = eval(bbbData.d);
     }

     this.Products = list;
     myProductsViewModel = ko.mapping.fromJS(this.Products, {});
     ko.applyBindings(myProductsViewModel);

 }

 function BindView(jsonProducts) {

      if (jsonProducts && ObjectTypeChecker.IsJsonObject(jsonProducts)) {
         zzzz = $.parseJSON(jsonProducts);
      }
      if (zzzz && zzzz.d) {
         lllll = eval(zzzz.d);
      }
      this.Products = lllll;
      ko.mapping.fromJS(this.Products, myProductsViewModel);
 }

但这不起作用:


 $(document).ready(function () {
     // Load all models
     LoadModels();
 });

 function onCategoryChange(event) {
     var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler", event.type, event.eventArgs);
    var jsonProducts = agent.GetProductsByCategory(event.eventArgs);
    BindView(jsonProducts);
 }

 function LoadModels() {
      var agent = new WtrStpJsAgent("WtrStpWireHandler", "NorthwindActionHandler", "GetMetadata", ["Products"]);
      var jsonProducts = agent.GetMetadata();

  // Load ProductListViewModel //////////////////////////////////
      myProductsViewModel = new ProductsListViewModel(jsonProducts);
      ko.applyBindings(myProductsViewModel);
 }

 function BindView(jsonProducts) {
      ProductsListViewModel.GetCurrentModel().BindViewModel(jsonProducts);        
 }

但是我仍然希望保持代码更精细,所以我喜欢使用后面的解决方案中描述的JS对象...因此,任何想法为什么它不起作用????

仍然需要帮助请: - )

1 个答案:

答案 0 :(得分:0)

如果您正在使用KnockoutJS并希望在更改var时更新UI,则需要使其可观察。

function ProductsListViewModel (bindingData) {
var self = this;  

this.Products = ko.observableArray();


//////////////////////////////////////////////
// Load
/////////////////////////////////////////////
this.BindViewModel = function (jsonProducts) {
    var _bindingData = jsonProducts;

    if (_bindingData && ObjectTypeChecker.IsJsonObject(_bindingData)) {
        _bindingData = $.parseJSON(_bindingData);
    }

    if (_bindingData && _bindingData.d) {
        _bindingData = eval(_bindingData.d);
    }

    self.Products(_bindingData);
    ko.mapping.fromJS(self.Products, self);
  };

另请查看http://knockoutjs.com/documentation/observableArrays.html