首先,謝謝TerryLee的推薦系列,本文就是在他的推薦系列看到的.
原文:Seamless inline text editing with ASP.NET AJAX
在開始之前,我們需要一個web form顯示這個行內文本Label和一個隱藏的TextBox會在編製的時候用來替換的:
<asp:ScriptManager ID="ScriptManager1" runat="server"
EnablePageMethods="true">
<scripts>
<asp:ScriptReference Path="behaviors.js" />
</scripts>
</asp>
<asp:Label runat="server" ID="Label1" />
<asp:TextBox runat="server" ID="TextBox1" Style="display: none;" />
請主意,我沒有使用TextBox的"Visibility"屬性來隱藏它,而是使用CSS來隱藏它.這點很重要,因為ASP.NET不會為一個隱藏的伺服器控制項產生HTML代碼,這會使它無法在用戶端操控.
為了方便示範,我將用Cache來填充我們的Label.你也可以很容易的使用資料庫,檔案,或者其他的儲存資料來代替.
protected void Page_Load(object sender, EventArgs e)
{
if (Cache["Title"] != null)
Label1.Text = Cache["Title"].ToString();
else
Label1.Text = "Default Title (click to edit)";
}
使用JavaScript來切換顯示
首先,我們需要一個Application Init handler來建立Label和TextBox的用戶端事件處理器.
>下面所有的代碼塊都是包含在 behaviors.js 中的.
var Label1, TextBox1; Sys.Application.add_init(AppInit);
function AppInit(sender) {
Label1 = $get('Label1');
TextBox1 = $get('TextBox1');
$addHandler(Label1, "click", Label1_Click);
$addHandler(TextBox1, "blur", TextBox1_Blur);
$addHandler(TextBox1, "keydown", TextBox1_KeyDown);
}
除了寫好了事件處理器,我還建立了一對全域變數來儲存對Label和TextBox元素的引用.這避免過多的調用 $get(),這樣多少能改善程式的易讀性.
接下來,讓我們來處理Label的click事件:
function Label1_Click() {
TextBox1.value = Label1.innerHTML;
Label1.style.display = 'none';
TextBox1.style.display = ''; // Thanks,Ira.
TextBox1.focus();
}
這裡發生一些事情:
- 首先,確保所有的東西在同步的情況下,在顯示TextBox之前總是將Label的當前值賦給它.
- 然後,我們通過切換兩個元素的display屬性,我們高效的將Label切換為TextBox.
- 最後,使用TextBox的focus()方法,使滑鼠定位到新顯示的的TextBox中.
這一連串的事件建立了一個直觀的使用者體驗.就好像只是簡單的點擊了文本就將滑鼠置於其中的TextBox中去了.
下一步,我們將處理TextBox的blur(失去焦點)事件:
function TextBox1_Blur() {
Label1.innerHTML = TextBox1.value;
TextBox1.style.display = 'none';
Label1.style.display = '';// Thanks, Ira.
}
這裡用TextBox的新值去更新Label的值,然後切換兩個元素的可見度.這隻是和Label1_Click()方法相反而已.
響應斷行符號鍵
一個有問題的情況是當使用者在編輯的時候按下斷行符號鍵.在TextBox中按下斷行符號鍵會提交表單併產生一個不希望發生的postback.而事實上,這個情況應該跟使用者完成編輯時將滑鼠的焦點離開TextBox是一樣的.
幸運的,解決方案很簡單:
function TextBox1_KeyDown(event) {
if (event.keyCode == 13) {
event.preventDefault();// Thanks, Alessandro.
TextBox1.blur();
}
}
這裡所做的是攔截按下斷行符號鍵的時候,並取消提交表單,然後使TextBox失去焦點,而使所有的東西都按我們期望的進行.
在任何人察覺到它消失前將它返回
如果我們不以某種方式將修改的內容儲存回伺服器中,這就沒有價值了.當然,UpdataPanel和_doPostBack()結合是一種儲存的途徑,通過部分postback.
然而,我認為使用JSON和頁面方法是另外一個更好的解決方案.
首先,我們需要一個靜態方法來儲存我們的資料.正如我剛才所說,為了簡便我使用Cache,但在你的代碼中你可以很容易的更新一個資料庫欄位或者寫入到檔案中.
[WebMethod]
public static void SetTitle(string title)
{
HttpContext.Current.Cache["Title"] = title;
}
好,現在我們已經有一個途徑來儲存我們的資料了.現在,我們所要做的就是修改我們的TextBox的"blur"事件處理常式來使用它:
function TextBox1_Blur() {
Label1.innerHTML = TextBox1.value;
TextBox1.style.display = 'none';
Label1.style.display = 'inline';
PageMethods.SetTitle(TextBox1.value);
}
就是這麼簡單
注意到頁面上一個UpdatePanel都沒有.那東西並不是必須的.使用JSON使這件工作很快,很高效.
如何使它更好
這隻是開始.一些潛在的改進的地方包括:
- 當TextBox失去焦點的時候檢查TextBox的內容,只有當確實修改過TextBox的內容的時候才調用SetTitle() .
- 如果使用一個比較慢的資料存放區,使用進度條可能是有利的.
- 使用一些分類的背景圖片來指示某些內容是可以進行行內編輯的.
- 處理ESC鍵(27)來取消編輯並返回到Label,而沒有改變Label的內容.
原始碼下載:
點此下載原始碼