ASP.NET AJAX Templates - Data Binding與Master-Detail連動

【ASP.NET AJAX Templates系列】


先前的ASP.NET AJAX Templates介紹都集中在如何將資料反應到顯示元素上,記得嗎? 在Server Control Template中,我們可以寫Eval也可以寫Bind,當使用Bind時,更改Template裡的資料,會反應回原始的資料來源上,這在ASP.NET AJAX Client Templates也做得到!

進一步來說,ASP.NET AJAX Client Templates的Binding寫法有三種:

  1. One-Way, One-Time:
    如同先前講過的{{ propName }}寫法,set_data時會將資料值寫入,之後就不再有任何互動。
  2. One-Way:
    要寫成{binding propName},set_data後,若當初提供資料來源的Javascript物件變動,該值亦會自動更新。 最主要應用於Master-Detail的情境。
  3. Two-Way:
    一樣是寫成{binding propName},但若同一屬性用在兩個HTML元素上,則更改其中一個,另一個也會跟著變化。

接下來,我們就將前述宣告式AJAX Templates的例子,做一些修改,改裝成Master-Detail形式,並透過Two-Way Binding加上酷炫的編輯功能。

首先,原本的Table維持不變,但要多加一個dataview:sys-key="dataViewObjName"的屬性,如此,便可利用這個變數名稱存取背後的Sys.UI.DataView物件。而這個物件,也將會是Detail View要Bind的對象。

我們建立一個<div>內包<fieldset>做為簡陋的Detail View展示:

    <div
    sys:attach="dataview"
    dataview:data="{binding selectedData, source={{ master }}}"
    class="sys-template" style="font-size: 9pt; width:300px;"
    >
    <fieldset>
    Person: {{Id}} {{Name}} <br />
    Score=<input type="text" value="{binding Score}" />
    </fieldset>
    </div>

值得注意的是,Score分數的部分,我們用了<input>,value則寫成{binding Score} [Updated: 目前版本的解析邏輯不佳,大括號內名稱前後不要插入空白],如此,當數字內容修改,就會反映回來源物件的Score屬性。但原先Table中我們寫的是<td style="text-align: right;">{{Score.format("N2")}}</td>,這是One-Time式Binding,不會即時反應值的變化,因此得改成{binding Score}的格式,但這衍生另一個問題,原來我們對數字做了格式化,加上千位號以及限定小數兩位,binding表示法裡必須直指Score,而不能用Score.format("N2")。要解決這個問題,要造convert函數,其表示法為{binding propName, convert=convertFuncName}。在我們的範例裡,我們新增一個函數fmtNum:

    <script type="text/javascript">
        function fmtNum(value) 
        { return parseFloat(value).format("N2"); }
    </script>

並改寫成<td style="text-align: right;">{binding Score, convert=fmtNum}</td>

 

如上圖所示,按了Id欄位,下方Detail View就會即時顯示所選取項目的內容,而修改Score後,修改後的分數會立即回饋到上方的Master View。

很酷吧!!

歡迎推文分享:
Published 05 December 2008 07:30 PM 由 Jeffrey
Filed under: ,
Views: 14,004



意見

# ChrisTorng said on 11 December, 2008 11:14 PM

是否能貼出此段完成後完整的程式碼? 前一個我有做出來,但這個怎麼弄都弄不出來...寫 {{ Score }} 時可以,但只是單向,這 ok。改成 { binding Score } 時就一定出錯,更別說 format...另在修改當中,有時會整個表格都沒顯示,不知道是怎麼回事...覺得偵錯好難喔...:(

# Jeffrey said on 12 December, 2008 08:05 AM

to ChrisTorng, 我發現我有個地方寫得不清楚。Detail裡寫了dataview:data="{binding selectedData, source={{ master }}}",則Master <tbody>要加上      dataview:sys-key="master",二者都取一樣的名字(master)才會相互對應。你先試試看是否問題出在這裡?

# ChrisTorng said on 14 December, 2008 07:38 PM

這一點我第一次就注意到了...如果這個寫錯的話根本完全不能動...

我現在的狀況是寫 {{ Score }} 可以執行,點上面連結下面就出現內容,修改值後上面不會更新,但點上面其他連結再點回來,下面會看到最新的值,可見該值已經成功改掉了,只差上面沒有更新,也就是沒寫 { binding Score } 的結果,看來是正常的。

一改成 { binding Score } 後,執行出現 js 錯誤:「Microsoft JScript 執行階段錯誤: Sys.InvalidOperationException: A markup extension with the name '' could not be found.」,錯誤點是 MicrosoftAjaxTemplates.debug.js 第 161 行: throw Error.invalidOperation(String.format(Sys.TemplateRes.cannotFindMarkupExtension, name));

剛剛定下心來追蹤 js 程式,終於發現問題了。

第 377 行的 spaceIndex = extension.indexOf(' '),其中 extension = " binding Score ",因此 spaceIndex = 0。我想到我是寫 { binding Score },改成 {binding Score} 去掉前後空白後,執行即正確了...原來良好的空白分隔習慣也不行啊 :( 我覺得它應該要先 trim() 之後再做 indexOf() 吧...

而下一行寫 if (spaceIndex !== -1),我本來以為是這裡寫錯了,但自己試過結果發現 !== 與 != 的結果是一模一樣的...不知 !== 的寫法有什麼其他意圖? 或者的確是寫錯了,只是 js engine 的執行結果恰好一樣 ?

剛剛才查到,確實有 !== 的語法...可能是為了效率吧...該 js 裡都這麼寫...

# ChrisTorng said on 14 December, 2008 08:18 PM

靜態宣告 people 如本文已經可以了,但 WCF 版一直改不出來,想說您接下來應該還會有一篇,會講如何將修改過的值回存 Server 吧...靜待下篇文章...

# Jeffrey said on 14 December, 2008 09:13 PM

to ChrisTorng,原來是空白問題,相信嗎? 我跟你做過同樣的事,一樣多加了空白,一樣Trace js才找出問題來。整理文章時一晃神便忘了加註進去,謝謝你的回饋,我想在這個Bug被改好前還會有千千萬萬的人中計,已把這點加註在本文中了。謝謝! 至於Update to WCF,有此計劃,但最近事多,可能會遲到一陣子,多多包涵。

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<December 2008>
SunMonTueWedThuFriSat
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910
 
RSS
創用 CC 授權條款
【廣告】
twMVC
最新回應

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication