著作權聲明:原創作品,允許轉載,轉載時請務必以超連結形式標明文章 原始出處 、作者資訊和本聲明。否則將追究法律責任。http://www.cnblogs.com/jintan/archive/2008/10/25/1319308.html
早晨不經意間看到園子裡 Bēniaǒ同學的《由var js = confirm("確認操作?");引發的技術難題》的文章,給我的第一感覺就是:哦,原來有這麼多人希望在webform中使用messageBox就像Winform中調用一樣方便。我一直以為沒有多少人去關注這麼一個小小的細節問題的,一年前正是因為我有同樣的想法,所以就決定做成伺服器端控制項,方便以後的項目中複用。
首先看看WinForm中的MessageBox.Show():
DialogResult result = MessageBox.Show("確定刪除嗎?", "提示", MessageBoxButtons.YesNo, MessageBoxIcon.Information);
if (result == DialogResult.Yes)
{
//相應的邏輯處理
}
else
{
//相應的邏輯處理
}
由於Winform中調用MessageBox.Show的時候會引起主線程掛起,直到使用者確認後才執行下面的代碼,而在javascript的windown.confirm()同樣可以實現這個功能,
if(window.confirm("你確定刪除嗎?"))
{
.....
}
如果要在伺服器端來實現,只需要用RegisterClientScriptBlock()註冊客戶指令碼就可以了。
現在又遇到2個問題:
用戶端點擊“確定”或“取消”的時候,伺服器端如何接收?有人說利用__dopostback('',''),沒錯,但是我們總不能在每個頁面都手工去寫這樣的代碼吧?那就得封裝成自訂控制項吧,只需實現IPostBackEventHandler介面。
用戶端show出confirm()訊息對話方塊後,只是讓用戶端的當前瀏覽器的主線程阻塞,並不會使伺服器端的主線程阻塞,這是肯定的!這也是我們遇到的最大難題,既然我們不能阻塞伺服器端的主線程,那我們能不能提供另一種代替的方式呢?就像下面的這段C#代碼:
protected void Button1_Click(object sender, EventArgs e)
{
//MsgBox是我們封裝的伺服器控制項
MsgBox.Show("需要刪除嗎?", (mSender, arg) =>
{
if (arg.Result == DialogResult.Yes)
{
Label1.Text = "OK,伺服器端執行的邏輯結果";
}
else
{
Label1.Text = "No,伺服器端執行的邏輯結果";
}
}
);
}
Show()方法的原型:
/// <summary>
/// 用戶端顯示confirm的訊息框
/// </summary>
/// <param name="message">訊息內容</param>
/// <param name="Message">回傳後處理的委託.</param>
public void Show(string message, Message objEventHandler)
實際上就是,在Show的第2個參數傳遞一個委託,其傳回值包含在arg中,說白了就是一個回調方法,該方法只有在用戶端點擊了“確定”或 “取消”後觸發。這樣用戶端點擊確定或取消時,把點擊的結果值回傳到伺服器端,伺服器端判斷並做相應的處理就OK了。這樣又帶來了另一個問題,這個委託到底是儲存在ViewState中還是Session中??如果儲存在ViewState,就會涉及到序列化、還原序列化的問題,委託是可以序列化的,但是不能保證其引用的對象可以序列化啊(即.Target有可能是Page等,這種不能序列化的對象),而且很多個物件放入ViewState中效率的確有點差。如果用Session呢?雖然能避免序列化帶來的問題,但是就涉及到Session的鍵名的問題,因為要確保頁面上的每個獨立的控制項鍵名不能重複,否則會引發很多問題。
public delegate void Message(object sender, MessageBoxEventHandler e);
//回調處理的委託
private Message MessageBoxCallBack
{
get
{
return this.Page.Session[GetSessionKey("MessageBoxCallBack")] as Message;
}
set
{
if (value == null)
{
this.Page.Session.Remove(GetSessionKey("MessageBoxCallBack"));
}
else
{
this.Page.Session[GetSessionKey("MessageBoxCallBack")] = value;
}
}
}
//產生一個控制項唯一的Session鍵
private string GetSessionKey(string key)
{
return key + this.Page.GetType().FullName + this.ClientID;
}
這樣,主要問題就基本解決了。希望大家多提意見。
Updated:2008-10-25,修改了Session key的擷取方法,對於不同頁面的分配不同的key
Code
//回調處理的委託
private Message MessageBoxCallBack
{
get
{
return this.Page.Session[GetSessionKey("MessageBoxCallBack")] as Message;
}
set
{
if (value == null)
{
this.Page.Session.Remove(GetSessionKey("MessageBoxCallBack"));
}
else
{
this.Page.Session[GetSessionKey("MessageBoxCallBack")] = value;
}
}
}
private string PageIdentify
{
get
{
if (ViewState["PageIdentify"]==null)
{
ViewState["PageIdentify"] = System.Guid.NewGuid().ToString();
}
return ViewState["PageIdentify"].ToString();
}
}
//產生一個控制項唯一的Session鍵
private string GetSessionKey(string key)
{
return key + PageIdentify + this.ClientID;
}
demo示範地址:http://www.webcontrols.com.cn/msg/
源碼下載:http://files.cnblogs.com/jintan/TestMessageBox.rar