[C#]在 .Net 上實現 Win Form 中 MessageBox 的確認視窗

  • 57866
  • 0

在 .Net 上實現 Win Form 中 MessageBox 的確認視窗

 

這篇文章的起源來自於一個小小的需求,就是確認。

web form的人都知道,利用JavaScript可以在使用者送出資料之前彈出一對話視窗進行確認,

在點選之後才會對網頁進行回傳資料。

 

但是,有沒有辦法做到像win form那樣子呢?

例如:

 

 

 

JavaScript最大的差異在於:

我希望按下送出之後,會先到server端的DB去尋找是否有相同的資料,

如果沒有,就新增;

反之,則彈出一個對話視窗提醒,

當我按下的時候,server端就會執行我想要的工作。

這個看似如此簡單的動作讓我這新手可是吃足了苦頭,

後來在網路上找到了文章有類似的技術提出,

利用了hiddenPageMethod來實現,

不過這依然不是我想要的,

 

之後又看到對岸的網友也是相同的問題,

而且還引起了不少討論,

原因是有很多人有同樣的需求:

希望系統能先到server端先去執行一段工作之後,

再把下一步執行的決策權重新送回使用者手中,

 

例如:假設我需要增加一個原料編號,但是系統發現資料庫中已經有相同的號碼了,

於是詢問我是否要繼續新增,

接著我判斷:雖然料號相同,但是進貨日期不同,

所以這筆資料依然有存在的必要,必須增加到資料庫。

 

再舉一個例子:

公司的行政在幫新進同事建立檔案,

發現某位新進員工擁有兩個碩士學位,

於是逐一建立,但是當key in第二筆資料時,系統發現了有重複的學歷,

於是詢問是否繼續新增?

當然這時負責的key in的人就要有所處理了,

他必須判斷這是失誤、還是說真的有雙碩士、雙博士學歷。

 

上面講的功能有經驗的大大也許很早就做過了,

AJAX環境底下透過某些ControlToolKit也可以完成,

之所以會想把這些記下來是因為小弟我自己基礎不好,

想要從CODE來了解dot net的運作過程,

太依賴套件會養成苟且的心理,

也沒有辦法呈現開發人員真正的核心價值,

想想看,如果隨便一個人靠著拖拉這些工具就可以寫程式

那我們這麼努力是為了甚麼呢?

而所謂的套件、ToolKit,說穿了也是別人包裝好的程式碼,

假如你是老闆,

你會希望請的人是幫你開發套件,創造新的智慧財產,

還是說只是個會照本宣科、拉拉元件的傢伙?

(也不是說貶低拉元件的人但是會寫網頁程式的人那麼多想要好的offer,就必須有不同的思維)

 

扯遠了,

先來談談在對岸看到的三篇文章,

這個議題首先在Bēniaǒ的部落格中提到,

(http://www.cnblogs.com/beniao/archive/2009/09/15/1317317.html)

之後由代碼亂了和volnet以及其他網友一起將這架構建立起來,

(http://www.cnblogs.com/jintan/archive/2008/10/25/1319308.html)

(http://www.cnblogs.com/volnet/archive/2008/12/03/1319609.html)

以下我整理了幾個觀念是急著踏入dot net的朋友來不及建立的,

1.      大多數人認為MessageBox.Show這種使用方式是約定俗成的必然,就好比當年大家在寫第一隻程式的時候,會用各種不同的方法輸出「HelloWorld」一般,包含了使用MessageBox.Show。然而Web的發展相對於Win Form來說,算是晚起步很多,這造成當一個程式開發人員用JavaScript alert出「HelloWorld」時,也會覺得這是一種必然,就跟Win Form一樣。

 

2.      針對進入dot net的程式開發者,微軟包裝了一套平易近人工具,大幅的降低了開發網站所需的時間和精神。藉由這個包裝,微軟想要打造一個跟開發Win Form相似的環境,來讓有Win Form經驗的人可以快速上手。我們可以在這方面推崇微軟,如果不是他們努力,就不會有那麼多生動有趣的網站如雨後春筍般冒出來,但也因此養成了程式開發者的依賴性,甚至有時會搞不清Win FormWeb Form的差異。其實這也不能都怪微軟,因為Visual Studio幾乎是最好整合開發工具,不僅讓寫程式省去了許多麻煩,也讓「寫程式」這件事普遍了起來。

然而,進入門檻的降低不代表每個人都可以解決更難的問題,也因為要讓自己有所提升,我們不可能永遠只停留在拖曳元件的階段,當你覺得開發一個網站變得更快時,往往不是因為自己變得更厲害,而是因為微軟幫你想的更多,這也是微軟程式開發人員貶值這麼快的原因之一。

 

「你跑的快不是因為你天生過人,是因為這條路已經鋪好柏油了。」

 

「有天,當大家都在柏油路上面賽跑時,你要怎麼贏過人家呢?」

 

所以,我認為要讓自己有價值,除了拖曳元件之外,還必須從coding的工夫做起。

 

3.      從本質上來說,上網是client端發送HTTP Requestserver端,然後server端送回資料給瀏覽器,最後斷開聯結。這邊要注意到關鍵點就是斷開的這個動作,在PostBack的架構中,程式開發者會將一些變數(或參數)儲存在頁面上,當form被傳回到server端的時候,server端就會根據那些變數來視情況是否需要執行畫面的更新。

 

        AJAX呢?AJAX透過非同步的更新機制向server送出要求,這個機制包含了XML檔案的交換,最初的需求是為了因應Outlook而發展的,但後來因為很多原因讓這個技術逐漸普及到Web上,這也應該算是無心插柳的一種結果吧。

 

那,要怎麼做呢?

 

來看一下傳統的confirm是在哪邊觸發的:

 

 

相信不用說大家也知道,confirm的出現是在送出Request之前。

接著來看我想要達成的功能:

 

 

有沒有發現,confirm是在資料庫搜尋完之後才出現的,

我在實作的過程中發現了幾個困難點,

 

1.      如何在AJAX的環境中,以C#呼叫JS產生confirm視窗?

2.      已經出現了confirm視窗,又要如何在按下之後發送Requestserver?

3.      送回去Request有沒有安全性的疑慮?

4.      傳值以及讓類似的副程式可以共用?

 

先要有個認知,

這個工作要在一次PostBack內完成是幾乎不可能,

因此我用了兩次PostBack來簡化這個流程,

幸好現在大家上網速度都有一定水準了,

多一次PostBack應該不會造成太大困擾…^^”

 

測試的方法是在頁面上放置一些元件,如下圖,

當使用者按下Button時,會先進行第一次PostBack,檢查TextBox中有沒有值,(步驟(1)(2))

(可以類比成檢查資料庫中是否有相同的資料)

要是有值(檢查出有相同的資料),以程式的方式呼叫JS confirm(步驟(3))

If(confirm==Yes),去Trigger頁面上的LinkButton,進行第二次的PostBack(步驟(4))

(LinkButton.Text = null, 避免誤按)

最後由LinkButton_Click的事件去將TextBox的值寫到Label(步驟(5))

 

 

 

 

 

Button1_Click:檢查文字方塊,然後呼叫confirm的函式:

 

 

 

Confirm的副程式:呼叫的方法是利用ScriptManager在頁面上註冊JS碼,

當使用者按下,用AJAX__doPostBack引發第二次的回傳,

並可藉key來傳遞參數。

 

 

 

最後,進行第二次PostBackLinkButton_Click事件中,

__EVENTARGUMENT 來參數來承接TextBox傳過來的值。

 

 

 

回到頁面上,

當你興高采烈的想要測試時,

畫面上卻出現了令你難以置信的錯誤:

 

 

 

 

原來問題是出現在微軟的安全性,

頁面的回傳不允許未經授權的回傳,導致EventValidation驗證失敗,

解決的辦法其中之一是按照提示,

Page裡的EnableEventValidation設定為false就可以了。

 

但是,這畢竟是個不安全的方法,

有沒有安全點的做法呢?

也是有的,方法就是不用__doPostBack

改成用JS ”Click” 頁面上的LinkButton

 

首先,改寫呼叫confirm的函式,解除由 __EVENTARGUMENT 來傳遞值,

然後用 .click() 來觸發LinkButton

 

 

 

傳值的部分,

有很多種方式,例如session

不過這邊我就地取材,選擇用LinkButtonCommandArgument來傳:

 

 

 

最後,接收傳回來的值:

 

 

 

來看看結果吧~

 

 

 

成功的輸出文字了!!

而且不必擔心安全性的問題!!

你也可以加上一些安全性的判別,

以及用switch切換你要執行的副程式: