網頁

淨水器,整水器,過濾器

最近在考慮買台淨水器(廠商又稱「整水器」),因為費用落差很大,花了點時間做點功課。

  1. 濾心、濾心、濾心;不要被五花八門的名詞嚇到,重點還是在濾心。
  2. 濾心的壽命;這是除了淨水器外一筆長期支出,所以也是要好好考慮。
  3. 選擇合適的過濾方式。
這裡面最難的是「3、選擇合適的過濾方式」。舉例,宜蘭家鄉三星,一個好山好水的地方,來自雪山山脈純淨的水(像不像廣告台詞),你選擇使用RO逆滲透…媽媽咪呀!

但我一直找不到「台灣各地水質」的資料,讓我想要了解一下現在居住地區水品質,再來參考購買那種過濾器,這是唯一我無法進行的地方。

結論:
有錢就買好一點;沒錢就買差一點。(凸)

參考:
淨水方法比較
如何選擇淨水器?

在學路畢業路--中文vs英文

說到了程式,那就不能不提一個大家的痛處「英文」, 中文和英文絕對是主導未來的兩種語言,學好中文與英文一樣重要,但在IT領域,我們不論是IT理論,還是IT技術絕大部分還是「英語系」國家開發或發明出來。很多人IT學不好或程式學不好,很大一份部理由是因為英文不好。

舉個例子,以前我學ASP時,六大物件總共六個單字,六個單字我就可以用的嚇嚇叫了,但現在的ASP.NET,你光翻開他的類別名稱(Class Name),嚇都嚇死了,而且越是深入你會發現,他們用的英文只會越深。

查MSDN也是一個例子,微軟的MSDN中文版很多人反應看不懂,看不懂是正常的,因為有很大一部份是用「機器人」去翻譯的,那怎麼辦,最後沒法子你還是要去看原文,很多人在這裡就…陣亡了,放棄了。

所以還是上面那句話,好好利用在校的時間,多多加強各位的英文,不要怪老師怎麼都是開原文書,那是在幫你,想想,剛才的影片,如果是你,會不會也是回答「I,I,I...我們還是說母語吧!」

 註:如果各位想走技術這條路且經濟許可,去「電腦補習班」、「英文補習班」我個人覺得是個不錯選擇,學校在科目的時間不夠集中,例如一門CCNA課程,要花二~四學期,太久了。好好利用課餘或假期,去電腦補習班幾個月就搞定了。不管是技術或語言,專精一項目,集中時間大量練習,是快速提升的不二法門。

在學路畢業路--我的學習經驗



這是我同學在Facebook上的留言,當你畢業後五年、十年後,如果還在技術方面的領域工作,一定都會跑出上面這個問題!而且現在新技術更新的速度又比以前更快,所以很多學IT的人到後面都會有「無力感」,舊的都還沒學完,新的又出來了,這時會有迷路現象出現,那怎麼辦?

其實我的答案已經在前面,了解分析選擇,選擇一條能讓你有熱情的路,除了熱情,學技術的人要有非常強烈的「求知慾」,除此之外,我建議可以從「生命週期長」的技術開始學起,通常這種技術很基礎,但能成為這方面頂尖專家的人又很少,舉個例:JavaScript,寫網頁的人很少也很難不使用它,他就是一個生命週期相當長的技術,但又很少人是頂尖專家。問問大家:

Function Blog(date, time){
this.date = date;
this.time = time;
}

Blog.prototype.sign = 'Bruce';

那有沒人看得懂以上程式?有沒有人會寫JavaScript物件導向程式?物件導向是未來程式開發的重點,我看過一行非常有智慧的程式碼,

if (me.today == me.yesterday) me.tomorrow = null; 

多有智慧的一句話,記起來,背下來,每當你在寫程式時就時時提醒自己,不要讓自己空白。

新增SQL Server 2005的AdventureWorksDB範例資料庫

如果你常需要上MSDN找SQL Server資料,你會發現,從SQL Server 2005開始,它所使用的範例資料庫改為AdventureWorks的資料庫,已經不是那習慣的Northwind與pubs資料庫。

有時候"看"不一定能懂,通常我們都會希望看看結果畫面,但這些範例都無法在Northwind及pubs執行,所以只好升級(新增)一下範例資料庫。

新增AdventureWorks資料庫很簡單:

  1. 下載 AdventureWorks資料庫安裝檔;(選第一個AdventureWorksDB.msi, 28053K,如有其他需求,再下載其他範例資料庫即可)
  2. 執行安裝程式;(我習慣把系統和資料分開放,所以我放在其他磁碟)
  3. 開啟SSMSE → 資料庫(右鍵) → 附加 → 加入(選所在路徑) → 確定

很簡單就完成了,可能是AdventureWorks的資料很大,所有就沒有提供使用*.sql的方法來新增資料庫。

好了,繼續K Document!@.@

補充一篇:Installing Sample Databases (主要針對SQL Server 2008的範例資料庫)

補充:[2010/4/28]
AdventureWorks資料庫資料表欄位會區分大小寫,請注意。

在學路畢業路--寫你的故事



各位有一天也會坐到那個位置,我不知道各位看了以上的影片有什麼感受,很多人到把學校當成一個「安全區」,也就是因為安全,所有就忘了要準備,而且是提前準備,讀讀書,考考試,反正能拿到畢業證書就好,如果你是這樣的想法,那你就要有當「工讀生」的準備,現在的社會環境只會一年比一年競爭,所以更要利用在校時間來準備,利用在校的時間來創造故事,除了專業證照,你還要有自己的故事。你有沒有故事可以講?

賴榮樞的工作經歷
 
這是我們資訊界一位老前輩多年來資歷,發表日期是4/9日星期五早上凌晨,為什麼我知道是凌晨,因為我還在準備資料,我睡不到幾個給小時早上五點半就又醒來準備,所以我很清礎,我也怕,我怕誤了大家。

像上面這些故事是你們最缺的,最常聽到畢業生說,我不知道自傳怎麼寫,如果你有上山下海的故事、南征北討的故事…怎麼會怕沒東西寫呢?我相信這些內容比專業證照更有說服力,比專業證照更有加分的效果。

我建議學校,從現在開始要求每個學生從大一開始打開104或1111求職網站,請每個同學每個學期交一份履歷表及自傳,當成每學期期末功課,這是每個出社會求職的人必備的功課,現在不做,何時做?這些資料不只求職可以用,連升學考試都超好用,每個學期review,才知道你有沒有在進步,讓師長為你把關,讓在校這些時間成為你最大的武器,儲備能量,爆發前的準備,這叫佈局未來

美國的研究機構做過一個實驗,他們針對哈佛大學100名頂尖的學生,做了45年的追蹤,結果得到一個驚人的數據:

1, 4, 36, 54, 5 (請先選擇)

答案在下面:
1% 優渥
4% 積蓄
36% 死亡
54% 救濟
5% 零工、流浪、乞討

請仔細看清楚這個數據,如果連世界頂尖學生所產生的曲線都是如此,我想我們也八九不離十,而這個研究機構還不死心,除了死亡的36%外,他們還接下去研究為什麼最後的59%(54%+5%)頂尖學生,最後會是失敗?最後他們發現,這些人生失敗的學生有以下三個特徵:


  1. 人生缺乏目標
  2. 對自己不忠實
  3. 為自己找藉口

各位,請用以上三個指標誠實檢視自己,如果以上三項都是沒有問題的人,我可以非常確定,你絕對是一個優秀份子,而且不論你在什麼領域,身在何處。

ps..請反白選取「答案在下面」的區塊。

in與not in的效能問題

這是藍色小舖討論in與not in效能的問題:

在in與not in,最終會轉換成where條件,記得。

有兩個關係:
一、Select出來的資料多少。
二、 Where帶的條件。

在1000筆資料裡,你是要使用in(包含)還是not in(排除)才會快?
in (10筆) / not in (90筆)?
in (90筆) / in (10筆)?

在100萬筆資料裡,你是要使用in(包含)還是not in(排除)才會快?
in (10萬筆) / not in (90萬筆)?
in (90萬筆) / not in (10萬筆)?

其 實兩題一模一樣,只是把資料量變大時,就看得出差異。
原則很簡單,選的那一個。

以第二題為例,
in (10萬筆) → 代表10萬條where條件
not in (90萬筆) → 代表90萬條where條件

不用我說應該就知道,「效能 差異」馬上分別出來,in與not in一體兩面,能下in就能下not in,找出的那一個才是重點。

在學路畢業路--愛你所選,選你所愛

首先感謝戴老師的邀請,讓我有機會跟大家分享一些工作經驗與人生經歷。我對各位來說雖然是個陌生人,但我很希望以下我的分享能真正幫助到各位,讓各位在未來不論是求學、升學或畢業後的求職路上都可以更順利。

話說,我在讀二技時認識一位宜蘭的同鄉學弟,他是讀五專,這位學弟人很特別,他從裡到外很非常的古人,文學氣習很重,他常來電腦教室休息室找我聊天,聊天的內容是…「討論他寫的詩」,他每次進來電腦教室休息室,從來不是來問「資管相關」的事,一陣子之後,我實在認不住了,我說:「學弟,你實在不適合讀資管,你要不要去轉學考,去考中文系」,雖然我們很投緣,在我的鼓勵之下,他後來下定決定去轉學考,而且也真的考上了。不過有點可惜是後來就沒連絡了。

各位同學,你們在校的時間是很寶貴,如果你問出社會工作的人,每個人都會跟你說,讀書最好當學生最好。但我想問的是:「你熱愛資管嗎?」,還是只是為選擇而選擇,考上了選上了就讀吧!進入之前或進入之後,你有好好想過,你適合當個資管人嗎?你有沒有好好研究什麼是資管系?這個資管系是學些什麼?學成之後是從事什麼工作?這些事,應該就大一時就想清礎,真正不喜歡就趕快轉系,不要浪費時間在這裡。(老師們對不起,叫學生不要讀了)

回來資管的問題,資管是你所選的嗎?那你讀了那怎久的資管,有沒有分析過什麼是資管?資訊管理,簡單說你們在學校會接觸到二大類的專業知識,一是資訊類、二是管理類,現在學校很用心,我在準備資料時,上來大華資管系網站查看,看到一個很棒的資訊:
大華資管課程:http://120.105.184.248/education.php?what_i_click=sub41
四技部課程與證照對照表
二技部課程與證照對照表
五專部課程與證照對照表
這是多棒的資訊,這可是我們以前沒有的,你們知道這是什麼嗎,這是餅,而且是大餅,學校在一開始就規劃好了完整的地圖給各位,也會按步就班的教各位如何拿到這個餅。

我以資訊課程為例:(魚骨圖)



各位你有沒有玩過「梯子遊戲」,上面是目的地,下面是出發點,在目的地到出發點之間畫上許多直線與橫線,然後選一個出發點,由直線往上,然後只要碰到橫線就必須轉彎。上面的圖形就像是梯子遊戲,梯子學校已經幫各位畫好了,但不同的是,各位你們可以「選擇」。

路很多,所以很雜,相信我,學校學的都只是「基礎」,學校教的是廣度而不是深度,但所有的技術都架構在基礎之上,李家同校長說過:「把基礎打好。」「基礎、基礎、基礎」如果各位一開始基礎都沒有打好,那其他事情就很難在進行下去。利用上面的資料,在好好思考你自己的特性,找出自己的專長,找出能讓自己有熱情方向,一項一項來,利用你還在學校的時間成為一位專家,那成為「專家」會不會很難,要花很多時間?時間是一定要花的,但會不會很難,見人見知。

我以大家最常使用的Office為例,沒有沒人是Word的專家?Excel的專家?PowerPoint的專家?這是你們學生時期用最多的三種軟體。你們知道嗎,外面有公司光一個PowerPoint就有做不完的生意,他們光教育訓練如何簡報、如何設計簡報…學費就貴的嚇人,比各位的學費還貴;我舉個例子,像簡報方法理論就有好多種,甚至還需要些心理學和行為學;你們有沒有去研究過這些,去學學這些,這是很能直接幫助到你學業或未來工作的知識,是值得投入時間去好好去專研一下!

自從我當爸爸就很會講故事,你們一定很久沒聽故事了,我來說個駱駝的故事:

一天,有一對駱駝母子在對話
小駱駝問:「媽咪!為什麼我們的眼睫毛比別人長」
母駱駝說:「兒子ㄚ!因為我們要橫越沙漠,長長的眼睫毛可以阻擋風砂不跑到眼睛。」
小駱駝再問:「為什麼我們有駝峰,它長的好奇怪!」
母駱駝再說:「兒子ㄚ! 因為我們要橫越沙漠,駝峰可以儲存養份及水份,讓我們可以通過最險惡的沙漠。」
小駱駝又問:「我們的腳的肉墊為什麼這麼厚,一點都不好看!」
母駱駝又說:「兒子ㄚ! 因為我們要橫越沙漠,腳的肉墊可以隔熱,別的動物都沒辦法像我們這樣,可以在沙漠行走,你看,我們可是一種偉大的動物。」
小駱駝沉默並思索了一陣子...................終於忍不住還是問:「媽咪!那我們在動物園幹嘛?」

Yahoo網頁:大專畢業生僅四分之一學以致用

各位我再說一次,如果你不喜歡資管,或是你讀資管讀的很痛苦,那你快走,那你就是學以不致用的四份之三,不要浪費人生在這裡(老師們對不起,又叫學生不要讀了),快點去找「沙漠」,去找一個能發揮能力的環境。

「天才,是放對地方的垃圾;垃圾,是放錯地方的天才。」

是要當垃圾或是天才,由你選擇

一首好詩

春有百花秋有月,
夏有涼風冬有雪,
若無閒事掛心頭,
便是人間好時節。

宋朝,無門慧開禪師

我的小孩(大寶貝)很受教,也很愛學,自己平常沒事就是去「翻」自己的書。而我們除非有很重要的事要處理,不然我們很少會讓他自己一個人獨自玩,但說實在,我們如果跟她說我們有重要的事要做,請她自己玩,她就會自己去玩,只會玩一玩突然跑過來叫你一聲「爸比、媽咪」,然後就又走開。

這陣子大寶貝的中文提升不少,尤其是「唐詩」,每天都在問「李白呢?」「王維呢?」…聽了只會跟Sunny(保母)或媽咪說:「這些古人真幸苦,都幾千年了還不能休息!」

大寶貝愛學習,這點讓我們很高興,所以我們也很用心在教,很多東西我都不覺得是我在教大寶貝,而是與大寶貝一起學習,例如,有次同事聚餐,聊天聊一聊,同學突然問了一題:「請問"茄子"的英文怎麼說?」我很直覺的就回答出來,這位同事說,你也有看「百萬小學堂」!我知道這個節目很紅,但…我連一集都沒看過(算秒的吧)。

我為什麼知道,因為寶貝的「童書」裡有,就是一張大大的圖片,加上中文與英文,英文看不懂,所以我 去查了字典,我會盡我所能教她「中、台、英」,有時覺得她們的童書一點都不童書,好多東西我也不會,那我又想教她,所以就必須自己下點功課,先學好,才有辦法教。

像為了在平常能與寶貝互動,例如念唐詩、弟子規、三字經,但寶貝不像小時候,書會一頁一頁看、一頁一頁的念,想要一次念完一首唐詩,有點困難,那我只好自己先背下來,然後我一句她一句,念的好快樂!

這週末(2010/4/25),難得好天氣,而且又伴隨著涼風,突然好想去海邊走走,我們選擇下午5:00~5:30出門,因為這個時間海邊的遊客都已經在回家的路上,太陽不會太大,溫度不會太高,也不會塞車。吹著海風,好像回到高中時代,看著小花狂跑興奮的樣子,看著大寶貝指著海一直說sea,沿著海岸線慢慢的走,突然發現大夕陽要下海了,這等美景,我快叫大寶貝過來,然後抱著她指著夕陽說,妳看夕陽要下海了,太陽公公要休息了,寶貝突然回我說:

「夕陽無限好,只是近黃昏。」

這…李商隱教的好。

學習,是一種生活化的過程。孩子帶給我們的樂絕對比苦還要多更多。感謝寶貝,讓我鏽鏽腦袋又上了新油 And 讓我生活充滿驚喜。

ps..
  1. 最前面那首詩,是我站在台中火車站月台前等火車時看到的,我覺得很棒,就默念幾次把它背下來。中文好美,詩好美。
  2. 茄子:eggplant。

在學路,畢業路--前言

在三月底收到老師的Mail,說想邀請我4/12返校演講,希望能為在校生和畢業生談談話,接到Mail的那一天,真的讓我想了好久,想了一整天,我在思考我是否要接下這個”任務”,最後我接下了,我認為我可以。 說真的,好久好久沒那麼認真了,那就認真是種「興奮」,從那一刻起,我不騙你,我無時無刻都在想,我可以送什麼給我的學弟妹們!我連睡覺做夢都在想。
這兩週的時間裡,除了上班外,晚上還要等小孩上床睡覺後,才會開始我的準備工作。

這兩週裡壓力不小,其實壓力不是來自要向100~200位學弟妹的演講,而且來自婆婆。

第一週還好,單純準備資料、大網、打草稿…,第二週,老婆走過來說,準備好了沒,說一次來聽聽!Oh~My God!我有沒有聽錯。時間已經很晚了,我一開始準備的資料很多,還沒什麼頭緒,你就等不及了,只見婆婆開了包「洋芧片」已經坐下了準備了。

第一次講的很亂,因為我連大網的前後順序都還沒決定,所以只是用報告的方式說明,我這個段落想說什麼,想講什麼,內容有什麼…這樣隨便聊聊都快二個小時。但其實心裡很亂,壓力很大,很怕老婆聽了會大笑。

娶到一位好老婆,真的是三生有幸。從第二週開始,老婆天天棒場專心聽,而且實在是一位超好的觀眾,從頭到尾都不會打斷我的談話,等我完整談完後才會給我些建議。她是一位七月要生產的媽媽,但為了這個演講,每天陪我凌晨一點以後。

一回生,
二回熟,
三回變高手,
四回打遍天下無敵手。

這要感謝我捨命相伴的婆婆。讓我有練習的對象,而且是會讓我產生壓力的對象。連能讓我產生壓力的人,也說OK,讓我心頭放心不少。

不過當天的情況有點不好,在Email中老師原本說是30分鐘的演講,加10分鐘的Q&A,但我準備之後,非常確定時間不夠,有請老師加到1.5小時加10分鐘Q&A,但最後因為種種的原因,還是只講了30分鐘左右,我精心準備的內容及約130張的投影片,很抱歉學弟妹們,你們沒辮法聽完。

回家後,想了很久,我還是決定把這些內容寫成文章,分享出來,讓有心的人可以受益,希望你們在學路、畢業路可以走的更順。

最後送你們一句話,這是讓我人生最受用的一句:

「世事洞明皆學問,人情練達即文章。」

很多事,說再多聽再多也沒有用,因為你不會有感受,好好的去過你的日子,你的人生。等有一天你通了,了解什麼是「世事洞明皆學問」你已經成功了一半,進而加強提升「人情練達即文章」的層次修為,那你一定可以有個精彩的人生。

ps..如果你對接下來一系列的文章有興趣,我個人希望你能做以下的功課,下載下面的PDF檔案,然後完成它,再接下去閱讀。

了解GridView事件(Event)

GridView實在是非常好入門的控制項,讓我們可以知一解百,也就是說,你如果能完全了解GridView控制項,那其他類似的資料處理控制項你也差不多學完了,所以對GridView的投資是非常值得。

除了要好好了解拉放之間滑鼠及Vistual Studio帶來的便利,我覺的學好GridView 事件,對學習ASP.NET有更重大的意義,一般控制項了不起就是Page_Load、Click、Change、Select這幾類,但GridView不同,因為它能幫你做好多好多事,所以他的事件就複雜很多,複雜不代表難。

GridView的事件多數都有前後之分(ing或ed結尾),這樣的事件流程讓我們可以對整個控制項或資料處理上有更靈活的操作,例如我要進行刪除作業:

刪除前 → 刪除中 → 刪除後

除了刪除中是我們無法操作的(因為刪除動作是在資料庫),我們可以在刪除前先做個Double Check,刪除後再Check一次及提示訊息。這是以前ASP所做不到的。「事件」可以說是ASP.NET一個很大的優勢,以下針對GridView事件做一個整理,而且每一個事件裡都把常用參數整理好,再加上一個小小範例,以後有GridView方面事件的問題,就可以直接查這篇,可以當成GridView事件快速入門篇。




RowCreated事件

''' <summary>
    ''' 建立 GridView 控制項中的資料列時發生。 
    ''' <summary>
    ''' <remarks>必須先為控制項中的每個資料列建立 GridViewRow  物件,才能呈現 GridView 控制項。建立 GridView 控制項中的每個資料列時,會引發 RowCreated  事件。</remarks>
    Protected Sub GridView1_RowCreated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowCreated
        'e.Row:取得所建立或繫結(Binding)到資料的資料列。 
        'e.Row.Cells(i):i是數值,存取資料列的第i個儲存格。
        'e.Row.RowType:在執行作業之前判斷資料列的型別。
        '範例:http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.gridview.rowcreated%28v=VS.80%29.aspx
    End Sub

RowCommand事件(常用)

''' <summary>
    ''' 按一下 GridView 控制項中的按鈕時發生。 
    ''' </summary>
    Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
        '通常判斷e.CommandName與e.CommandArgument來進行一些額外的事件處理
        'e.CommandName有些內建關鍵字,會引發特定行為與事件(http://msdn.microsoft.com/zh-tw/library/system.web.ui.webcontrols.gridview.rowcommand%28v=VS.80%29.aspx)
        'e.CommandName:取得自訂按鈕命令名稱
        'e.CommandArgument:取得自訂按鈕命令引數
        'e.CommandSource:存取引發事件的按鈕控制項

        '自訂按鈕,命令名稱為"cancelSelected"
        If e.CommandName = "cancelSelected" Then
            GridView1.SelectedIndex = -1
        End If
    End Sub

我們自訂的命令名稱都需要在RowCommand事件做處理。例如GridView沒有取消選取的功能,我們就可以自訂按鈕,然後命名為cancelSelected,然後在RowCommand事件來進行取消選取的功能。

RowDataBound事件

''' <summary>
    ''' 資料列繫結(Binding)至 GridView 控制項中的資料時發生。 
    ''' </summary>
    ''' <remarks>控制項中的每個資料列必須都繫結(Binding)至資料來源中的資料錄,才能呈現 GridView  控制項。資料列 (由 GridViewRow  物件表示) 繫結(Binding)至 GridView 控制項中的資料時,會引發 RowDataBound 事件。這可讓您提供事件處理方法,用於每次發生這個事件時執行自訂常式,例如修改繫結(Binding)至資料列之資料的值。GridViewRowEventArgs 物件會傳遞至事件處理方法,讓您存取正在繫結(Binding)之資料列的屬性。若要存取資料列中的特定儲存格,請使用 GridViewRowEventArgs 物件的 Cells 屬性。您可以使用 RowType 屬性決定繫結(Binding)那種資料列型別 (標頭資料列、資料列等)。</remarks>
    Protected Sub GridView1_RowDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) Handles GridView1.RowDataBound
        'e.Row:取得所建立或繫結(Binding)到資料的資料列。 
        'e.Row.Cells(i):i是數值,存取資料列的第i個儲存格。
        'e.Row.RowType:在執行作業之前判斷資料列的型別。
        '1. DataRow:GridView 控制項中的資料列。(常用)
        '2. Footer:GridView 控制項的頁尾資料列。
        '3. Header:GridView 控制項的標頭資料列。
        '4. EmptyDataRow:GridView 控制項中的空白資料列。
        '5. Pager:GridView 控制項中的頁面巡覽列。
        '6. Separator:GridView 控制項中的分隔列。

        '如果資料的類型是「資料列DataRow」,第一個儲存格文字改為粗體。
        If e.Row.RowType = DataControlRowType.DataRow Then
            e.Row.Cells(1).Text = "<b>" & e.Row.Cells(1).Text & "</b>"
        End If
    End Sub

例如我們想幫GridView的每個刪除按鈕加上一段JavaScript,就必須寫在這裡。想像成DataSource把資料一列一列送給GridView,而每一列資料與資料列綁定時,就會發生RowDataBound事件(一列發生一次),所以如果你想做的事是對整個GridView產生作用(每個刪除按鈕),那就必須寫在RowDataBound事件。

刪除事件

''' <summary>
    ''' 按一下資料列的 [刪除] 按鈕時發生 (但在 GridView 控制項刪除資料列之前)。 
    ''' </summary>
    Protected Sub GridView1_RowDeleting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView1.RowDeleting
        'e.Keys:取得欲刪除那筆資料的PK值。查看DataKeyNames屬性,就可以知道PK值有那些。
        'e.Cancel:Boolean,True表示取消刪除動作。
        'e.Values:取得要刪除那筆資料的"欄位值"
        'e.RowIndex:目前要刪除這筆資料在GridView中的索引值。注意,Index及PK是不同東西。Index指的是排序順序,另外GridView有啟用分頁,假設每頁10筆,則第2頁第一筆資料的RowIndex是0非10。

        If e.Keys("CustomerID") = "ALFKI" Then
            Response.Write("此資料不能刪除!")
            e.Cancel = True
        End If
    End Sub

如果你想手寫刪除程式,必須寫在RowDeleting事件。

''' <summary>
    ''' 按一下資料列的 [刪除] 按鈕時發生 (但在 GridView 控制項刪除資料列之後)。
    ''' </summary>
    Protected Sub GridView1_RowDeleted(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewDeletedEventArgs) Handles GridView1.RowDeleted
        'e.AffectedRows:刪除筆數。
        'e.Keys:取得欲刪除那筆資料的PK值。
        'e.Values:取得要刪除那筆資料的"欄位值"。
        'e.Exception:若刪除發生例外,可透過e.Exception取得例外相關資訊。
        'e.ExceptionHandled:Boolean,當例外發生且e.ExceptionHandled沒有為True時,會值接在網頁上顯示例外的錯誤畫面。

        '確認是否有刪除例外發生
        If e.Exception Is Nothing Then
            Response.Write("刪除" & e.AffectedRows & "筆資料:" & e.Keys("CustomerID") & "," & e.Values("CompanyName"))
        Else
            '不要產生錯誤畫面
            e.ExceptionHandled = True
            Response.Write(e.Exception.Message)
        End If
    End Sub

編輯事件

''' <summary>
    ''' 按一下資料列的 [編輯] 按鈕時發生 (但在 GridView 控制項進入編輯模式之前)。 
    ''' </summary>
    ''' <remarks>RowEdit沒有ed事件(RowEdited),因為進入Edit模式後,是由RowUpdating/RowUpdated接手處理。</remarks>
    Protected Sub GridView1_RowEditing(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView1.RowEditing
        'e.Cancel:Boolean,True表示取消編輯動作。
        'e.NewEditIndex:取得或設定要編輯之資料列的索引。

        '按下「編輯」按鈕的這一資料列(e.NewEditIndex)進入編輯模式
        GridView1.EditIndex = e.NewEditIndex
    End Sub

''' <summary>
    ''' 按一下處於編輯模式之資料列的 [取消] 按鈕時發生 (但在資料列結束編輯模式之前)。 
    ''' </summary>
    Protected Sub GridView1_RowCancelingEdit(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles GridView1.RowCancelingEdit
        'e.Cancel:Boolean,True表示取消編輯模式。
        'e.RowIndex:目前要取消這筆資料在GridView中的索引值。

        '取消編輯模式
        'e.Cancel = True 
        '在VB中「-1」(負1)也有取消的意思
        GridView1.EditIndex = -1
    End Sub

更新事件

''' <summary>
    ''' 按一下資料列的 [更新] 按鈕時發生 (但在 GridView 控制項更新資料列之前)。 
    ''' </summary>
    Protected Sub GridView1_RowUpdating(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView1.RowUpdating
        'e.Keys:取得欲更新那筆資料的PK值。
        'e.Cancel:True表示取消更新動作。
        'e.OldValues:取得更新那筆資料,除了PK欄位之外的原始值。
        'e.NewValues:取得欲更新那筆資料,除了PK欄位之外的更新值。
        'e.RowIndex:目前要更新這筆資料在GridView中的索引值。

        Dim cmpName As String = Trim(e.NewValues("CompanyName"))
        If cmpName.Length = 0 Then
            Response.Write("公司名稱不可為空白")
            e.Cancel = True
        End If
    End Sub

利用更新前做一些錯誤處理,避免不正確的資料進到資料庫中。或是手寫更新程式,也必須寫在這裡。

''' <summary>
    ''' 按一下資料列的 [更新] 按鈕時發生 (但在 GridView 控制項更新資料列之後)。 
    ''' </summary>
    Protected Sub GridView1_RowUpdated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs) Handles GridView1.RowUpdated
        'e.AffectedRows:更新筆數。
        'e.Keys:取得欲更新那筆資料的PK值。
        'e.OldValues:取得更新那筆資料,除了PK欄位之外的原始值。
        'e.NewValues:取得欲更新那筆資料,除了PK欄位之外的更新值。
        'e.KeepInEditMode:Boolean,是否讓GridView維持在編輯模式。
        'e.Exception:若更新發生例外,可透過e.Exception取得例外相關資訊。
        'e.ExceptionHandled:Boolean,當例外發生且e.ExceptionHandled沒有為True時,會值接在網頁上顯示例外的錯誤畫面。

        If e.Exception Is Nothing Then
            Response.Write("成功更新 " & e.AffectedRows & " 筆資料.")
        Else
            e.ExceptionHandled = True
            Response.Write(e.Exception.Message)
            e.KeepInEditMode = True
        End If
    End Sub

分頁事件

''' <summary>
    ''' 按一下其中一個頁面巡覽區按鈕時發生 (但在 GridView 控制項處理分頁作業之前)。 
    ''' </summary>
    ''' <remarks>以程式設計的方式設定 PageIndex  屬性時,不會引發這個事件。</remarks>
    Protected Sub GridView1_PageIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView1.PageIndexChanging
        'e.Cancel:Boolean,True表示取消分頁選取模式。
        'e.NewPageIndex:取得或設定要在 GridView  控制項中顯示的新頁面索引。

        '按下「分頁」選擇,讓GridView顯示指定的分頁(e.NewPageIndex)
        GridView1.PageIndex = e.NewPageIndex
    End Sub

''' <summary>
    ''' 按一下其中一個頁面巡覽區按鈕時發生 (但在 GridView  控制項處理分頁作業之後)。 
    ''' </summary>
    Protected Sub GridView1_PageIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.PageIndexChanged
        '在產生「Page 1 of 10 .」的提示資訊。
        Response.Write("Page " & (GridView1.PageIndex + 1).ToString() & " of " & GridView1.PageCount.ToString() & ".")
    End Sub

選取


''' <summary>
    ''' 按一下資料列的 [選取] 按鈕時發生 (但在 GridView 控制項處理選取作業之前)。 
    ''' </summary>
    ''' <remarks>以程式設計的方式設定 SelectedIndex  屬性時,不會引發這個事件。</remarks>
    Protected Sub GridView1_SelectedIndexChanging(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSelectEventArgs) Handles GridView1.SelectedIndexChanging
        'e.NewSelectedIndex:取得或設定要在 GridView  控制項中選取之新資料列的索引。
        'e.Cancel:Boolean,True表示取消選取事件。

        '按下「選取」按鈕的這一資料列(e.NewSelectedIndex)進入選取模式
        GridView1.SelectedIndex = e.NewSelectedIndex
        '另一種寫法
        'GridView1.SelectedIndex = GridView1.SelectedIndex
    End Sub

''' <summary>
    ''' 按一下資料列的 [選取] 按鈕時發生 (但在 GridView 控制項處理選取作業之後)。 
    ''' </summary>
    Protected Sub GridView1_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.SelectedIndexChanged
        '在選取完成後,顯示所選取資料列第三個儲存格(Cells從0開始計算)的資料。
        Response.Write("You selected: " & GridView1.SelectedRow.Cells(2).ToString() & ".")
    End Sub

排序事件

''' <summary>
    ''' 按一下排序資料行的超連結時發生 (但在 GridView 控制項處理排序作業之前)。
    ''' </summary>
    ''' <remarks>按一下排序資料行的超連結時,會引發 Sorting 事件 (但在 GridView 控制項處理排序作業之前)。</remarks>
    Protected Sub GridView1_Sorting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles GridView1.Sorting
        'e.Cancel:Boolean,True表示取消排序事件。
        'e.SortDirection:取得或設定排序 GridView  控制項的排序方向。
        'e.SortDirection.Ascending():小到大,A~Z。
        'e.SortDirection.Descending():大到小:Z~A。
        'e.SortExpression:取得或設定運算式,用來排序 GridView 控制項中的項目。

        '切換大小排序
        If e.SortDirection = SortDirection.Ascending Then
            e.SortDirection = SortDirection.Descending
        Else
            e.SortDirection = SortDirection.Ascending
        End If

        '欄位Brithday不能排序
        If e.SortExpression = "Birthday" Then
            e.Cancel = True
            Response.Write("You cannot sort by Birthday.")
        End If
    End Sub

''' <summary>
    ''' 按一下排序資料行的超連結時發生 (但在 GridView 控制項處理排序作業之後)。 
    ''' </summary>
    Protected Sub GridView1_Sorted(ByVal sender As Object, ByVal e As System.EventArgs) Handles GridView1.Sorted
        '顯示排序方法及排序欄位
        Response.Write("Sorting by " & GridView1.SortExpression.ToString() & " in " & GridView1.SortDirection.ToString() & " order.")
    End Sub

有夢最美

前兩天比較早去接大寶貝,因為比較早到,所以有多點時間可以和保母多聊兩句。

我們這位保母算是「奇葩型」的人,做事、想法都很特別,而我們剛好又很喜歡這種有自己想法的人,更重要的是她小孩真的帶的象不錯,她不會像一般媽媽型或家庭式的保母,她每天都有活動、有課程、有進度,而大寶貝的成長,我們也看在眼裡,所以教給她我們很放心。

那我們聊什麼呢?她聊說,她想要去「讀大學」去「圓夢」,她年輕時,因為小孩很難帶,一直被其他保母「退貨」,所以她決定自己下來帶,所以人生中就少了那一段記憶,現在小孩都大了,男的帥女的美,學歷也都不錯(還沒畢業),她已經沒有「後顧之憂」。

現在她想去做一些「自己想做的事」去完成「自己的夢想」。她想跟她女兒說:「媽媽也有大學畢業。」

人生有方向,是多麼重要及快樂的一件事。


下週,我會寫一系列「在學路畢業路」的文章,裡面有一段落就是在談夢想及目標。那我有什麼夢想呢?

我的夢想清單:

我想學吉他
我想學簫

這是我十多歲時就想進行而未進行的事,我也一直記在心裡,有一天我一定會完成它,然後背著吉他和簫,踏著Bike到任意之處,進行演奏。我還做過一個夢,我跟寶貝成為音樂人,還出了張音樂CD,真是快樂的夢。

Sunny,加油。
有夢的人,怎麼看都美。

GridView裡使用CommandName來變換背景色

原程式來自藍色小舖

Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
        If e.CommandName = "Add" Then
            Dim rowindx As Integer = CType((CType(e.CommandSource, Button).NamingContainer), GridViewRow).RowIndex

            For i As Integer = 0 To GridView1.Rows.Count - 1
                If i = rowindx Then
                    GridView1.Rows(rowindx).BackColor = Drawing.Color.Red
                Else
                    GridView1.Rows(i).BackColor = Drawing.Color.White
                End If
            Next
        End If
    End Sub

這是網友提問的問題,其中Aska提供了一段程式碼,這段程式碼讓我們可以使用程式的方式來取得所在的GridView裡RowIndex,算是進階等級的使用方法,其中有些屬性是比較少使用,順道了解一下。

重點在CType這一段落:

e.CommandSource:取得命令的來源。

註:就是取得引發此命令的來源(即控制項),然後轉換為Button物件(因為是由Button來引發)。

.NamingContainer屬性:取得伺服器控制項命名容器的參考,其建立唯一命名空間,在具有相同 Control.ID 屬性值的伺服器控制項之間作區別。

GridViewRow類別
:表示 GridView 控制項中的個別資料列。


RowIndex屬性
:取得 GridView 控制項之Rows集合的 GridViewRow 物件索引。

ASP.NET+jqPlot實作線上即時統計圖表(Chart)

如果你以前想在ASP.NET下做畫一些統計圖表(Chart),那可能會選擇Microsoft Chart Controls,這個東西叫「伺服器控制項」,也就是說它吃的資源是「伺服器」,雖然是個不錯的解決方法,但還必須K點資料才能上手玩玩。題外話,在Visual Studio 2010裡我有看到已經內建Chart控制項。

那有沒有「輕鬆入門」的Chart套件,網路世界無奇不有,首先先介紹一套jQuery的plug-in的函式庫:jqPlot,我認為這個plug-in有幾點很不錯:

  1. 免費
  2. chart功能完整
  3. 輕鬆入門
  4. 範例清礎
  5. javascript(資源是吃Client)

一般而言,這種Chart的東西通常都要收費,而且費用還不低。而這套jqPlot,除了免費而且使用簡單,你只要產出jqPlot所需要的格式參數,那它就會幫你把想要的統計圖表一張一張產生出來。

1. include the Files

請在頁面<head>裡加入以下Script,路徑請自行修改。

<!--[if IE]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
<script language="javascript" type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script>
<link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />

這裡有幾件事要注意,
  1. 第一行那個if IE一定要放,不然在IE圖會出不來
  2. 只能在IE8上執行,IE8以下圖一樣會出不來(這個bug我抓了好久)
  3. 可以將jquery-1.3.2.min.js換成jquery-1.4.2.min.js
第1,2點請注意,如果使用者不會使用到IE來看圖,你可以不放。第3點,1.4.2版的執行效率比1.3.2版提升不少,我測試使用上是還沒有碰到問題。

2. 增加一個目標區(div)

也就是要讓jqPlot畫圖的區塊,重點是div的id屬性,等一下只要把id值給jqPlot函式,jqPlot就會幫你畫美美的圖表了。

3. 建立圖表參數

使用上,我會建議你直接上jqPlot Examples, 去找你所需要圖表,然後它會跟你提醒兩件事:

  1. 此Chart除了上面的Script外,必須額外加那些plug-in,這些plug-in放在plugins目錄中,將這些附加到上面Script的後面即可。
  2. 此Chart所需要的參數格式

第2點,就是我們的重點,也就是說,要透過ASP.NET與ADO.NET產生所需要的格式。

1. 實作:問卷分析統計圖表

我設計了一個問卷活動的程式,收集到問卷資料後,必須產生相關的統計圖表。在資料庫部份,我將所有資料選項都化為0,1,2這種字串(char),單選就簡單,利用SQL語法做加總即可,複選就複雜一點,我在存入資料庫時,先把所有選擇值整理成一個"0,1,3,5,7,9"的字串格式儲存,統計時再取出放到陣列來進行每一項目的統計。

資料庫和統計程式,我不方便透漏。不過運作的演算法可以分享一下。

一、在Default.aspx放入一個PlaceHolder控制項,拿來放產生後的javascript。

二、在Default.aspx放入畫圖參數(請查jqPlot Examples),範例:


/*問卷統計圓餅圖*/
var plot1 = $.jqplot('chartQ1', [line1], {
    title: 'Q1職業分析',
    seriesDefaults: { renderer: $.jqplot.PieRenderer, rendererOptions: { sliceMargin: 8} },
    legend: { show: true }
});

注意:
  1. 建立對應的div區塊,id必須與$.jqplot('chartQ1',[line1]…的'chartQ1'相同。
  2. 產生數據參數名稱,必須與[line1]相同
  3. var plot1參數名稱不能重覆
  4. 如果在同一頁產生多張Chart,程式會依順序執行,如果其中一個發生問題,會影響後面全部Chart的產生
第1,2,3點很好理解。第4點意思是說,假設我一次要產生10張Chart圖,所以我的畫圖參數就會有var plot1, var plot2, var plot3...var plot10(由上而下排列),每個plot1...plot10帶不同參數, 假設line5產生的數據有問題,所以造成plot5的圖產生失敗,那接下來plot6,7,8,9,10就都不會產生(這個bug我也抓了好久)。

三、Default.apsx.vb產生必須的參數值[line]


Dim line As New Literal()
'資料庫處理…
'整理出相關統計數據…

'整理出我們需要的參數格式
line.Text += "<script type='text/javascript'> var " & lineName & " = [['網管(" & Q1sum1.ToString & "票-" & ((Q1sum1 / sum) * 100).ToString("##.##") & "%)'," & Q1sum1.ToString() & _
"],['採購(" & Q1sum2.ToString() & "票-" & ((Q1sum2 / sum) * 100).ToString("##.##") & "%)'," & Q1sum2.ToString() & _
"],['網咖主(" & Q1sum3.ToString() & "票-" & ((Q1sum3 / sum) * 100).ToString("##.##") & "%)'," & Q1sum3.ToString & _
"],['系統人員(" & Q1sum4.ToString() & "票-" & ((Q1sum4 / sum) * 100).ToString("##.##") & "%)'," & Q1sum4.ToString & _
"],['其他(" & Q1sum5.ToString() & "票-" & ((Q1sum5 / sum) * 100).ToString("##.##") & "%)'," & Q1sum5.ToString() & "]]</script>"

'加到PlaceHolder控制項
phJS.Controls.Add(line)
End Sub

範例:
我最後在Default.aspx就產生了以下了javascript程式碼:
<script type='text/javascript'> 
var line1 = [['網管(12票-7.19%)',12],['採購(37票-22.16%)',37],['網咖主(17票-10.18%)',17],['系統人員(17票-10.18%)',17],['其他(0票-%)',0]]
</script>

四、最後看看我們的畫面:



有沒有一種感動到想哭的感覺。 我在一個畫面上產出45張統計圖(含圓餅圖及長條圖),速度要看電腦,原因在上面說過了,但基本測試都還不錯,而且Server Loading又輕,讓我有那種相見恨晚對感覺。

GridView「新增」功能破解完整攻略

上一次我們提到,GridView不直接支援「新增」功能,小弟不才,經歷無數汗水(寫程式都吹冷氣,你騙誰!)與黑夜(自己不上床睡覺,還黑夜!),終於讓我寫出一個完整版的GridView新增功能,也就是說,依照此法,你光使用一個GridView控制項就能完整擁有「SELECT(顯示)、INSERT(新增資料)、DELETE(刪除)、UPDATE(更新)」等四大完整功能,不用再使用「GridView + FormView」、「GridView + DetailsView」…分開來實作「新增」功能,我們讓他們通通結合在一起,而且用起來「很順、有夠順、非常順、順到忘了他們的存在」。

此密技應該拿來出版賣錢,但恩師的讀者服務做的實在很好,所以我也決定「捐」出來送給大家。只有一個條件,請不要整篇轉貼,我的Blog沒有廣告,但也希望流量統計圖可以好看些^_^!

第一步:新增GridView + sqlDataSource

這個步驟沒有什麼技巧,一、先在畫面上拉GridView,二、新增資料連線,重點在sqlDataSource設定裡的「進階」必須產生Insert、Delete、Update等語法,這樣等一下GridView裡的新增才能直接使用此sqlDataSource的Insert語法。

第二步:增加「新增」功能

  1. 進入GridView的「編輯樣板」,選擇「EmptyDataTemplate」樣板;;
  2. 拉一個DetailsView進去EmptyDataTemplate,資料來源選擇與GridView同一來源(sqlDataSouce);原因上面說了,我們要使用同一資料來源裡的Inster語法;
  3. 設定DetailsView的DefaultMode為「Insert」;
  4. 勾選DetailsView的「啟用插入」

進入DetailsView的「編輯欄位」,找「選取的欄位」最下方的「CommandField(中文版是:新增、插入、取消)」,把ShowCancelButton屬性設為「False」;因為在EmptyDataTemplate樣板中DetailsView取消按鈕不會有作用,留下會讓使用者把到「把柄」說:「你的程式有Bug!」

第三步:在GridView新增觸發「新增」功能的按鈕

  1. 選擇GridView的「編輯欄位」;
  2. 加入一個「ButtonField」,移動一下位置;設定ButtonField屬性Text:設定為「新增」;
  3. (重點)設定ButtonField屬性CommandName="GridInsert"(名稱請自訂)

第四步:後置程式碼,讓GridView的「新增按扭」觸發「EmptyDataTemplate」樣板

我們必須寫第一段程式碼,讓我們的「新增」按鈕被按下時,能進到「EmptyDataTemplate」樣板,進而觸發裡面的「DetailsView」的Insert模式。我們必須透過GridView的RowCommand事件來觸發一些事情,進而進到「EmptyDataTemplate」樣板。

先想想,什麼時候我們會用到EmptyDataTemplate樣板?一般我們都在裡面寫「Sorry, No any data.」或「金排球,沒有任何美女圖!」就是你送給GridView的資料是「空空」的時候,所以我在RowCommand事件就是要讓GridView空空的,什麼都沒有。

Protected Sub GridView1_RowCommand(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView1.RowCommand
        '中斷GridView與sqlDataSource的「綁定,Binding」,讓GridView進入EmptyDataTemplate樣板
        If e.CommandName = "GridInsert" Then
            GridView1.DataSourceID = Nothing
        End If
    End Sub

第五步:終極必殺--讓DetailsView有自動返回GridView的功能

接下來就是要教各位如果讓GridView提升為無敵控制項的密中密,請大家好好學,結果一定會讓大家大吃一驚,原來…我們永遠把事情想的太複雜

之前在「GridView」的「EmptyDataTemplate樣板」的「DetailsView」按「取消」鈕是沒有作用的,而你如果想回原始的GridView中,只能單純使用Browser的「上一頁」來解決,不過這不是我的菜,事情終有解決的一天,讓我們來解決這個大魔王把!

進入「EmptyDataTemplate樣板」:以下的解法有兩種,但不可思議的是它們還共用同一段程式碼(for Visual Studio 2010/.NET Framework 4.0)。

五之一:在DetailsView外使用Button按鈕

在EmptyDataTemplate樣板中隨便找個地方,從「標準」工具中拉一個「Button」控制項
設定Button屬性:ID為「bntBack」,Text為「Back GridView」
  1. (點重一)然後請在畫面上點Button控制項點兩下,進入程式碼編輯模式;第一:請注意程式碼最後,沒有Handles bntBack.Click;第二,那我們要寫什麼程式呢?…想想可樂果…我們前面是如何進行「EmptyDataTemplate樣板」,讓GridView的資料是「空空」的時候,相反的,我要離開EmptyDataTemplate樣板呢?讓GridView的資料是「不是空空」的時候。

Protected Sub bntBack_Click(ByVal sender As Object, ByVal e As System.EventArgs)
        'sqlDSNW請修改為自己的名稱
        GridView1.DataSourceID = "sqlDSNW"
    End Sub

完成,總共寫了「四行」程式碼就完成一個超完整「新增、修改、刪除、更新」功能的「GridView」,重點是新增功能可正常運作,而且不用依賴Browser的「上一頁」來返回GridView。(大家拍拍手)

但這個按扭放在DetailsView之外,怎麼看都不順眼,對不對!那我們再來「手動自訂『取消」按鈕」吧。

五之二:在DetailsView內手動自訂取消鈕

原本DetailsView裡的「取消」鈕已經被我們設定為「False」,所以我們要新增「假按扭」來取代原有的「取消」鈕。
  1. (重點)在DetailsView中進入「編輯欄位」,選擇下方「CommandField(中文版是:新增、插入、取消)」,然後轉換為TemplateField欄位,回到DetailsView中;
  2. 選擇「編輯樣板」的「InsertItemTemplate」;新增作用在InsertItem樣板;
  3. 從「標準」工具中拉一個「Button」控制項(LinkButton或ImageButton也可以)到InsertItemTemplate樣板中;
  4. 設定Button屬性:Text為「Back GridView」;ID為「bntBack」;
  5. (重點)在Button控制項上點兩下,進入後置程式碼;
  6. 結束所有樣板編輯

Protected Sub bntBack_Click1(ByVal sender As Object, ByVal e As System.EventArgs)
        'sqlDSNW請修改為自己的名稱
        GridView1.DataSourceID = "sqlDSNW"
    End Sub

ps..這裡我是故意把兩個Button取同樣的名稱,我發現在VS2008與VS2010(或應該說.NET Framework 2.0與4.0的CLR)一些差異,在VS2008中,會建成Click與Click1兩個副程式,但在VS2010中它會很聰明共用同一個Click副程式,所以會少打一行程式碼。但實務上應該會不有人那麼無聊沒事放兩個Back的按鈕,而且還取相同名稱。當然也可能是表頭放一個、表尾放一個,但名子不要一樣,一行程式應該不會影響你很多效能與時間吧!

以上就完成了可以回到GridView的DetailsView了,重點很簡單:
  1. 不管是在DetailsView內外,都必須使用「Button控制項」(含LinkButton與ImageButton),因為我們需要Click副程式來做些事;
  2. DetailsView的Button控制項,點兩下,讓Visual Studio幫我們產生對應Click副程式;
  3. DetailsView的Button控制項,因為我們希望是放在「插入」旁邊,所以我們必須先讓「CommandField」轉換為TemplateField欄位,再進入「InsertItemTemplate」放入Button控制項,點兩下,讓Visual Studio幫我們產生對應Click副程式;
  4. 在Click副程式裡,讓GridView與sqlDataSource回復綁定(Binding),GridView就會取消EmptyDataTemplate樣板,回到原始顯示資料的模式。
ps..基本上只要資料控制項有支援「Insert」功能,都能拿來做GridView的新增功能控制項,再利用上敘方法加入返回GridView頁面功能即可。

一個簡單的後台連線防護程式

需求很簡單,公司的網頁雖然有對外公開,但總是會有一些管理後台,這些管理後台的「安全」通常就要花費程式人員許多的時間,但想了想,公司會使用這些後台的人都是由「內網」來連線,而且Server也在內網,而且我也看不到有人下班後還在使用這些管理後台裡工作,所以就想出了這段簡單的程式碼來做第一段的防護,發現效果還不錯,分享出來給各位:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
  Dim localIP As String = ""

  '取得連線的IP
  localIP = Request.ServerVariables("REMOTE_ADDR").ToString
  Dim IP() As String = localIP.Split(".")

  '判斷前三碼是否為內網IP段
  If IP(0) <> "192" OrElse IP(1) <> "168" OrElse IP(2) <> "3" Then
    Response.Write(">script type="text/javascript">
alert('此網頁只能從公司內網進入!網頁將轉向首頁!')
>/script>")
    Response.Redirect("http://kkbruce.blogspot.com/")
  End If
End Sub
End Class

原理很簡單,我只是1.取得遠端IP,2.然後分割為陣列,3.然後比對一下,不對的話,4.就請他離開!因為轉向很快,所以那段javascript不會顯示,各位可以加強一下。

唯一的代價是,「完完全全無法從外網連線」。不過還是有解,我們或許可以偷放個參數,當參數為true時,就停用此段程式碼。

各位不要小看以上這段小程式,基本上他的作用不管是內網還是外網都可以很正常的運作,怎麼說?例如我們的Server是放在外面的機房,但只要我們公司對外的IP是固定IP,我們一樣可以使用以上的方式來過濾不安全的IP連線,不是公司的IP就不給連線,現在的ADSL要申請固定IP那麼簡單,所以這一段就留給大家去解決。

拜師學藝

古人說:「師父領進門,修行看個人。」
我最近終於去拜師了,我試了好久,應該這樣說,我之前沒時間沒機會沒現金,所以我在資訊的路上通常只能走「無師自通」的路,像之前為了研發公司自有DDNS服務,就花去我近半年的時間,實在好累,不過也很爽,你能做出來別人沒有的東西,就是一種成就。
不過,無師自通真的好難,難在你要花很多、很多、很多身心靈,找資料、看文件、看書,經過時間及經驗的累積之後,還不一定能會。

自學ASP.NET有二年的時間吧?以前一直使用ASP,從ASP.NET 1.1出來,學過一、二個月,實在受不了那鬼東西,我就回頭寫ASP,轉換的過程是很痛苦,後來慢慢感受到好像不學不行了,才又開始去接觸ASP.NET 2.0,我接觸時,.Net Framework 3.5剛出來,所以市面上的書還都是ASP.NET 2.0,根本就分不清有什麼差別,還在想新人的問題:「現在學2.0的東西,會不會3.5又要重學一次,要不要等3.5的書出來再來學!」

還好,我習慣了無師自通的學習,就開始去收集資料,這才發現,微軟在這方面有很大進步,他知道「不斷改版」是玩技術的人很重的擔子,舊的還沒學玩或才剛開始玩出一點心得,新的又出來了,所以從.NET Framework 2.0開始,是使用「積木」的方式,以.NET Framework 2.0為,再上面加一些東西積木,就稱3.5,再加一些東西就成了現在的.NET Framework 4.0

以上這點是很重要的一項,讓我決定花時間重新學習的Key point。因為我分析過後,這樣花時間下去才有「值得」,不會因為技術更新而讓我現在學習的知識、經驗很快就沒有用處,而且不管是升級或不升級,我在.NET Framework 2.0或說ASP.NET上的投資是看得見的,不會只是曇花一現。再來,因為我有VB及ASP的底子,切入可以比一般人快,所以決定…升級我的大腦。

ASP.NET越玩越好玩,入門很簡單,真是「快樂的不得了」,但想要打怪、練功、升級時就發現沒那麼容易了,想找看看有沒有外掛可以使用時,才發現,書局裡的ASP.NET教科書…入門買了浪費錢,進階買了看不懂,什麼開發伺服器控制項之類的;另一重點,如果真的有不錯的書,又通常是C#版本,我比較笨吧,沒有力氣去玩「雙語」。久了你就會發現,你一直停留在「練功」,做些簡單的小東東,無法前進了。我一直很清礎自己的情況,所以我了解我是需要找一個「師父」了。

老實說,我覺得上天對我實在不錯,總是在這種關頭就會出現我需要的貴人,這個貴人還正是ASP.NET界的高手,雖然他的書我很早就買了,也看得差不多了。就像很多學生學英文時會說的笑話:「abcd~26個一個一個字母我在認識,但它們結合在一起時,我一個都認不得!」書是看了很多,但實作作戰時,總是卡卡的,總是只能打些小怪小腳,對魔王總是一點辦法都沒有,所以當我收到消息,第一時間馬上打了電話說:「請收我為徒!」

不過事情總是不會太順利。對不起,師父說名額滿了,請等下一次。又要Oh~My God!老天呀!你不是要給我機會,成功成仁嗎?沒關係,我有心等,我願意當個後補。

不順利其實是轉機。二週後,一通沒見過電話號碼打進來手機,金剛戰士嗎?你後補補上了,師父說願意收你為徒,你是否願意?費用10億歐元,你就能得到方舟門票。我願意,我願意,我100個願意,我馬去典當內褲透過20世紀最偉大的發明,在數分鐘之內完成交費註冊的動作,拿到門票,成為師父門下學徒。

當張無紀學了九陽真經,打通任督二脈,成為高手之後,「再來學什麼武功都快」。功,我還沒練完,但是就是有一種「打通任督二脈」的感覺,可能是我已經花了二年的時間在ASP.NET的武功上,師父說一點通一點,說一點通一點,以前是死看,沒有「懂」與「通」,但經過師父的一招一招的解說,一招一招的教,每次總有醍醐灌頂大升級的感覺。

跟對人很重要。我要好好感謝我的師父MIS2000 Lab。自從跟了MIS2000 Lab學藝之後,在公司有如毀滅戰士Doom裡的戰士:答~答~答。感覺都對了,魔王來吧!

魔王:GridView的「新增」功能

在師父的書中11.2節(page 11-5)提供了一個GridView的新增法,GridView如果你是直接使用控制項是沒有新增功能的,且引用微軟MSDN的說法:「GridView控制項不直接支援資料來源「新增」資料的功能。

未拜師之前,我還真的寫信問過MIS2000 Lab,說書中範例有一大缺點,「取消」無作用。也就是說,原始以為我們在GridView新增完成後,如果要回上一頁(顯示資料)畫面,會很直覺去接「取消」,但多方測試、查資料、發信問MIS2000 Lab本人之後,發現是沒有辦法的。只能單靠Browser的上一頁按鈕來回去。這個結,一直在我心中。

MIS2000 Lab寫過一篇文章:「拳怕少壯」,他的人生觀、職場觀是很不錯的小品,出版社應該找他出點這類的書,我可是很認真的看。

看起來,我還很壯,拳頭還可以,所以寫出了:
GridView完整破解攻略--可自動返回上一頁(資料顯示頁),讓GridView擁有完整的「新增、刪除、修改、更新」四大功能,而且操作流程上「順的不得了」。
只需要一點點點點點點點程式,欲知結果,請下回分曉!

感謝恩師。(我可以說他是張三豐嗎!)

Visual Studio 2008 Default Browser(預設瀏覽器)

我們在安裝好VS2008開發工具時,一般都會使用內建網頁伺服器來做測試、除蟲…等工作,但有個問題一直困擾我,就是VS2008預設啟動的「瀏覽器」是IE,但各位也知道,IE雖然是市佔率最高的瀏覽器,但它可不是最好debug的瀏覽器,所以我一直在想,有沒有辦法可以改變這個預設值。

但我找遍VS2008裡「工具」→「選項」所有細項,沒有就是沒有,也慢慢養成,VS2008開IE,我再打開Firefox,把IE裡的網址copy過去,再關閉IE,開始在Firefox工作。

這樣的步驟很多餘,我一直想要按「在瀏覽器中檢視」→「Firefox」→「debug,工作」。

今天終於找到了解決辦法。@.@""

「檔案」→「瀏覽方式」;


就那麼簡單,想要什麼自己加,你也可以在已加入的列表點兩下,使用選擇的瀏覽器來開啟內建網頁伺服器,「Ctrl+S」好用,「Ctrl+Shift+S」「Ctrl+Shift+W」也還不錯,但還是把「功能表列」看清楚,設定的東西玩玩無差,不要亂按確定就好。