2013-05-30 55 views
0

我是一個C#開發MVC希望從事件處理程序的糾結我的客戶端JavaScript演變爲一個更有組織的系統,所以我開始看knockoutjs。最初它看起來很棒,關於如何將它放入我的生產環境的想法正在迅速形成。我嘗試了一些基本原則,所有這些原則都很好地工作,沒有問題。 我想嘗試一些更復雜的東西(這是特定於我正在工作的項目),但我無法得到它的工作。MVC4 Knockoutjs綁定到一個列表<>

我試圖尋找其他的例子,但沒有找到任何匹配的東西。

我想要做的是將對象列表綁定到客戶端。在這個例子中,我使用了一個人的列表,我在頁面上顯示了這個人的列表,並且希望通過ajax請求更新頁面上的所有人(這個例子純粹是爲了測試而編寫的,但是原理就是我後)。

我使用knockoutjs映射插件做模型映射爲我

我的C#代碼

public class HomeController : Controller 
    { 
     public ActionResult Index() 
     { 
      List<Person> people = new List<Person>() 
      { 
       new Person() 
       { 
        FirstName = "Neil", 
        LastName = "Diamond" 
       }, 
       new Person() 
       { 
        FirstName = "Bob", 
        LastName = "Seager" 
       }, 
       new Person() 
       { 
        FirstName = "Tom", 
        LastName = "Jones" 
       } 
      }; 

      return View(people); 
     } 

     public JsonResult UpdateNames() 
     { 
      Random r = new Random(); 
      var num = r.Next(1, 100); 
      List<Person> people = new List<Person>() 
      { 
       new Person() 
       { 
        FirstName = string.Concat("Neil", num.ToString()), 
        LastName = string.Concat("Diamond", num.ToString()) 
       }, 
       new Person() 
       { 
        FirstName = string.Concat("Bob", num.ToString()), 
        LastName = string.Concat("Seager", num.ToString()) 
       }, 
       new Person() 
       { 
        FirstName = string.Concat("Tom", num.ToString()), 
        LastName = string.Concat("Jones", num.ToString()) 
       } 
      }; 
      return Json(people, JsonRequestBehavior.AllowGet); 
     } 
    } 

我看來

@model List<TestingKnockout.Models.Person> 

@{ 
    ViewBag.Title = "Home Page"; 
} 

@for (int i = 0; i < Model.Count; i++) 
{ 
    <p>Firstname: <strong data-bind="text: [@i].FirstName"></strong></p> 
    <p>Lastname: <strong data-bind="text: [@i].LastName"></strong></p> 
    <hr /> 
} 

@section scripts 
{ 
    <script src="~/Scripts/knockout-2.1.0.js"></script> 
    <script src="~/Scripts/knockout.mapping.js"></script> 
    <script type="text/javascript"> 
     var viewModel = {}; 
     $.ajax({ 
      url: "/Home/UpdateNames", 
      cache: false, 
      success: function (data) { 
       viewModel = ko.mapping.fromJS(data); 
       ko.applyBindings(viewModel); 
      } 
     }); 

     setInterval(function() { 
      $.ajax(
       { 
        url: "/Home/UpdateNames", 
        cache: false, 
        success: function (data) { 
         ko.mapping.fromJS(data, viewModel); 
        } 
       }); 
     }, 5000); 
    </script> 
} 

任何幫助將不勝感激,或者如果我錯過了顯而易見的內容,或者如果這個問題出現之前請給我指出正確的方向。

問候

編輯

與托馬斯和羅德尼兩個答案,看來我是不正確的假設淘汰賽的一些行爲。淘汰賽必須以整個模型作爲JSON開始,然後從那裏更新。我希望能夠用最初的數據呈現HTML,然後用knockout來處理更新,但我認爲我的方法是不正確的。 與托馬斯的HTML和羅德尼帶頭從代碼(小的改動JSON序列化和人們觀察到的),我改變了我的看法代碼以下和一切似乎很好地工作,現在

@model List<TestingKnockout.Models.Person> 

@{ 
    ViewBag.Title = "Home Page"; 
} 

<div data-bind="foreach: people"> 
    <p>Firstname: <strong data-bind="text: FirstName"></strong></p> 
    <p>Lastname: <strong data-bind="text: LastName"></strong></p> 
    <hr /> 
</div> 
@section scripts 
{ 
    <script src="~/Scripts/knockout-2.1.0.js"></script> 
    <script src="~/Scripts/knockout.mapping.js"></script> 
    <script type="text/javascript"> 
     var viewModel = { 
      people: ko.mapping.fromJS(@Html.Raw(Json.Encode(Model)))  
      }; 
     ko.applyBindings(viewModel);  

     setInterval(function() { 
      $.ajax(
       { 
        url: "/Home/UpdateNames", 
        cache: false, 
        success: function (data) { 
         ko.mapping.fromJS(data, viewModel.people); 
        } 
       }); 
     }, 5000); 
    </script> 
} 

我會喜歡爲Tomas和Rodney提供答案。不得不選擇,我認爲羅德尼對托馬斯的幫助最大。

+1

你也想看看SignalR嗎?這非常好,所以你不必手動輪詢服務器。 –

+0

民意調查只是爲了舉例,我打算使用信號R – OJay

回答

3

使用Tomas答案中的HTML。

您將需要序列化您的初始c#模型到一個JavaScript列表。一個流行的方法是使用JSON.NET庫。

添加此C#代碼到視圖的開頭

@using Newtonsoft.Json 
@{ 
    var jsPeople = Html.Raw(JsonConvert.SerializeObject(Model)); 
} 

更換所有你的JavaScript的以下各項:

var viewModel = { people: ko.observable([]) }; 
viewModel.people(ko.mapping.fromJS(@jsPeople)); 

setInterval(function() { 
    $.ajax(
    { 
     url: "/Home/UpdateNames", 
     cache: false, 
     success: function (data) { 
      viewModel.people(ko.mapping.fromJS(data)); 
     } 
    }); 
}, 5000); 

$(document).ready(function(){ 
    ko.applyBindings(viewModel); 
}); 

哦,我要指出,我已經使用jQuery的在這裏文檔準備就緒時執行applyBindings。

2

你錯過了應該如何使用這一點。你應該設置你的視圖模板(HTML)。然後以JSON格式加載數據(或者它可以與正在提供的頁面一起)。

應用綁定可以在加載數據之前或加載初始數據集之後完成。但那應該只發生一次。你應該放開你習慣使用ASP.NET MVC視圖呈現模型的地方。 Knockout應該負責將數據綁定到您的HTML模板。

您可以在加載數據或加載數據之前控制屏幕上顯示的內容。而你的應用程序邏輯將在你的JavaScript中,你操縱對象和UI更新由Knockout處理。

<div data-bind="foreach: people"> 
    <p>Firstname: <strong data-bind="text: FirstName"></strong></p> 
    <p>Lastname: <strong data-bind="text: LastName"></strong></p> 
</div> 
+0

原諒我,我想我理解你正在解釋的概念,但我正在努力應用現場。如果願意,你可以用更多的代碼來闡述?特別是在我的問題中給出的代碼,我應該改變什麼才能使它工作? – OJay