2009年10月25日 星期日

Silverlight的Ink機制

Silverlight一直以來就有所謂的Ink手寫功能,過去我很少提到這部分,最近有一位讀者問到操作的方式,因此一併在BLOG上介紹。

InkPresenter控制項是筆墨的關鍵,你可以透過InkPresenter的Strokes集合屬性,把一個或多個Stroke物件加入Strokes集合中,而Stroke物件的StylusPoints屬性所表達的就是一群連續的點,用來在畫面上呈現出各種線條。

而透過滑鼠的MouseMove事件,我們可以很輕易的取得滑鼠經過的每一個點,例如:


private void InkCanvas_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
//將每一點加入NewStroke
NewStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(InkPresenter1));
}
如此一來,我們就可以輕易的建立出可以手寫繪製的畫板了。

[測試範例] [完整範例程式碼下載]
當然,Ink機制也可以跟Multi-Touch配合,關於這部分在下一期的Run!PC當中會配合Multi-Touch一併介紹與說明,有興趣的讀者可以參考Run!PC 11月號。

2009年10月17日 星期六

找出專案的潛在問題

最近因為一些公司的專案忙得昏天暗地,剛好前陣子是TechDays,整個重心都放在TechDays上,又同時得顧及手上的一些專案工作,實在是有蠟燭兩頭燒的感受,很多事情即便列出優先順序,卻發現實在是時間不足,我常常有一早起來,坐在電腦面前,突然間一天就過去了的經驗,一整天都處於緊繃和忙碌中,偏偏email又一直來,突發事件不斷...似乎沒法喘口氣釐清一下事情的整個狀況。

回顧十多年的軟體開發生涯中,偶而會陷入這樣的情境中,這時候除了救火之外,找出問題的核心變得相當重要,我想起過去一個前輩告訴我的,他分享了他的經驗,因為每一個主管手上的專案和工作都相當多,實在沒有辦法深入到每一個項目中。可是,如果不深入到項目中,怎麼能發現問題在什麼地方呢? 怎麼發現專案哪邊可能有潛在的問題? 並且提早處理呢?

我之所以會突然想到這位前輩的經驗分享,是因為我最近就碰到了這些問題,手上同時有很多專案,坦白說我沒法深入每一個專案,但是畢竟我是負責這些專案的管理者,我得要能夠預先發現問題,確保專案能夠順利進行。

這時候,『問對問題』變得很重要,過去的經驗讓我發現,確實有很多主管問的問題都一針見地,立刻可以掀出專案潛在的問題,讓可能發生的意外無所遁形,我過去以為這些PM大概天賦異稟或是有常人沒有的洞察力,但是我後來發現,其實似乎也有一個方式可以遵循。

其實道理很簡單,當年,那位前輩各訴我,當你發現某些地方越被找理由蓋起來,那些地方就越要掀開來看,包含主管自己對自己的要求也是一樣,人都有惰性,你發現自己越不想碰的問題,越表示那些地方將有著大問題,甚至,有些其實是自己潛意識根本不想去碰的部分。做主管的得要能察覺這些現象。

自己寫了多年的程式碼,也帶了多年的專案,越來越覺得真的是這樣,當某些模塊,在專案討論的時候,總是被成員找理由(理由多半是很合理且冠冕堂皇的)跳過或是忽略,當時程總是被粗估簡化,當驗收條件總是被模糊化,系統流程好像不是很solid,那很抱歉,這些地方多半都有著嚴重問題,特別是我們(開發人員)很喜歡把規格模糊化,或是你在進行專案會議時,發現針對某些部分專案成員的回答似乎總是有些不很確定,那幾乎可以斬釘截鐵的肯定告訴你,這表示這些地方將來真的會有大問題。

大多數主管其實心裡也知道,只是因為自己也很忙,所以下意識的跳過了,想說算了,下次開會的時候再盯一下,這時候千萬要提醒自己,別忘了這一塊肯定是有問題的。

過去的經驗告訴我真的是這樣,自己潛意識越是不想打開的那段程式碼,裡面暗藏著越多的bugs,在一天的工作計畫中,自己越不想去碰的那塊,越是會出問題,反過來說,如果你專挑自己越不想碰的事情先做,越能夠讓一天的工作順利進行,想想還真的是這樣。

道理很簡單,大家都懂,只是要下定決心去做,似乎還真不容易。

2009年10月12日 星期一

ASP.NET 4.0中的URL Routing

在今年TechDays 2009的ASP.NET 4.0場次中,我介紹了一些ASP.NET 4.0的新功能,其中有許多功能都是在 3.5 SP1中展露頭角,可能在MVC中,也可能在Dynamic Data中,這些3.5 SP1中的功能在釋出後深受開發人員的好評,很多開發人員反映是否可以加入在Web Form中,因此MS也就從善如流的照辦了,其中一個功能就是 URL Routing機制。

過去URL Routing機制僅被MVC和Dynamic Data支援,如今ASP.NET 4.0當中直接納入了Routing類別,也就是說,WebForm也直接支援了Url Routing機制。

URL Routing機制可以讓我們很輕易的建立出REST風格(請參考REST一下吧)的網址,也可以讓我們輕易建構出類似Dynamic Data風格的網址,像是:
http://myWebSite/Product/Edit/XBOX
我們可以用上面的網址來表達要編輯一筆產品資料,產品名稱為XBOX。這樣的網址呈現方式不只更加的直覺清楚,同時也有著相當大的延展性,例如,我們可以用底下的網址表明要編輯名稱為Student資料表中的David同學的資料:
http://myWebSite/Edit/Student/David
當然,也可以用底下這個網址來表達要編輯名稱為Employ資料表中的Eric員工的資料:
http://myWebSite/Edit/Employ/Eric
而這兩個網頁理論上行為上完全一致,其實可以用同一個.aspx頁面來執行。

也就是說,傳統的WebForm .aspx頁面,在編輯不同的資料表時,幾乎註定要寫不同的頁面(來維護多個資料表),如果有三五個資料表要維護,這不是問題,反正透過Wizard很快就可以建立出這些.aspx頁面,但是,如果是一千兩千個資料表,那你就要好好思考了...

為何傳統的WebForm不能用『一個』.aspx頁面來處理這一兩千個資料表呢? 其實每個資料表的編輯行為(Behaivor)不是都一樣嗎?

是的,但是這背後的原因很多,主要是因為SqlDataSource、FormView、GridView的行為和DataBinding機制,造成了ASP.NET注定讓UI層和DB的相依性過高(在.aspx頁面中有SQL指令或是DataForm/DataGrid的template中有資料表欄位名稱),導致很難(不是絕對不行)設計出一個.aspx頁面來同時處理數個資料表的編輯動作。反過來說,如果想要這樣做,肯定就無法輕易的用FormView或是GridView來完成,而需要在.aspx頁面上動態地產生資料表欄位所對應的UI欄位,不過很慶幸,這我們已經在ASP.NET 3.5 Sp1中透過Dynamic Data技術實現了。現在我們透過DynamicData技術,已經可以動態的針對資料表來產生前端UI所需要的Control,也就是說,我們可以輕易設計出以一個.aspx頁面就處理多個資料表的功能了...(這背後涉及的技術很多,以後有機會我們慢慢談...)

既然在技術上已經可以實現,那URL也要稍加配合吧?所以,ASP.NET Dynamic Data Web Site/MVC開始支援URL Routing機制,過去我們的網址都是:
http://WebSite/Folder/PageA.aspx?Para1=abc&Para2=123
這樣的網址看起來真的很遜,當使用者看到上面這樣的網址時,會發現整個網址的設計其實是反映出應用程式開發的『資料夾』架構,這有幾個缺點:

1.安全性降低:因為使用者很容易知道我們把哪一個功能(頁面)放在哪一個目錄下。
2.網址無法表現出功能性:上面的網址只會呈現出資料夾,而非使用者在意的功能,這些資料夾規畫對於使用者來說沒有意義。

如果我們可以把它改成:
http://WebSite/FeatureName/ActionName/Parameter
這樣的網址,則網址就較有意義了,同時也符合我們架構大型(或超大型)ASP.NET應用程式的需求,因為我們可以事先規劃功能,然後將不同的功能切割為不同的網址表示法,這樣不管網站是由幾個人同時開發,都不會搞出亂七八糟的Folder和網站架構。而對於開發人員來說,也不需要管另一個開發人員到底把功能架在哪一個Folder的哪個.aspx頁面,在網頁和網頁需要溝通或是彼此呼叫的時候,只需要依照最初的SD規劃,redirect到某一個url(例如需要編輯產品AK47的資料時可以redirect到http://WebSite/Edit/Table/Products/AK47),而這個網址自然會被URL Routing機制導成真正的.aspx頁面,這對於開發大型網站也頗有助益。


OK,了解其意義之後,接著看ASP.NET 4.0怎麼架構Url Routing機制,其實很簡單,只需要在Global.asax中撰寫程式碼設定即可:

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Routing.RouteTable.Routes.Add("test1", _
New Routing.Route("Search/{ProductName}", _
New Routing.PageRouteHandler("~/WebForm1.aspx")))
End Sub
我們透過Routing這個新加入的類別,將『http://WebSite/Search/{產品名稱}』這樣的網址對應到WebForm1.aspx,如此一來,當使用者在網址列上輸入(或程式設計師透過redirect將網址導入『http://WebSite/Search/AK47』時,就會執行導http://WebSite/WebForm1.aspx

而開發人員可以在WebForm1.aspx中透過RouteData.Values("ProductName")抓取到參數值『AK47』,這樣就可以輕易實現URL Routing功能了。

2009年10月7日 星期三

[推薦] 網路電台

很久以前,在我小時候的那個年代,我很喜歡一個電台『中廣音樂網』,每天24小時不停放送的音樂,大部分都是我很喜歡的類型,輕音樂、爵士、或是抒情搖滾,但是前幾年可能因為電台的經營策略或是改組,這個電台轉型了,轉型之後我就再也不是忠實聽眾了,因為整個電台的類型和我喜歡的差異頗大。

最近這幾天,因為某些原因,我在醫院住了幾天,陪著家人,在偶然的機會下,發現了兩個網路電台(沒有FM/AM頻道的,就只能在網路上聽),由於我時常會有需要在辦公室外工作的機會,因此身上總是會帶著一台小型的Router,可以透過LAN或是USB 3.5G網卡上網,並且建立一個Wireless的工作環境,因此收聽網路電台對我來說是比收聽實體電台還來的方便。

聽了幾天,覺得很喜歡,因此推薦給大家,
http://www.goodnews.org.tw/classic.php
http://www.goodnews.org.tw/ccm.php

這兩個網路電台是佳音廣播電台建立的,其實佳音廣播電台是一個台北的區域小電台,沒有很好的資源,或是很強的經濟後盾,但是隨著藉著現在科技的進步,可以讓電台不需要用很高的成本,就可以透過網際網路對全世界廣播,把好聽的音樂傳遞出去。

就跟以前的中廣音樂網一樣,這兩個電台的屬性當是我相當喜歡的類型,讓人可以安靜下來,特別是我在醫院,所以相當受用。

如果你偶而心情不好,如果你需要安靜思考,如果你希望能夠整理情緒、重新有一個平靜安穩的心情,那不妨聽聽這兩個頻道,在如此忙碌競爭的環境中,或許會讓你有不一樣的感受。

2009年10月1日 星期四

[轉貼]多點觸控程式設計競賽 (及 如何用滑鼠模擬多點觸控)

隨著微軟最新作業系統 Windows 7 終於進入上市最後倒數階段,微軟與.DotBlog舉辦「Windows 7 多點觸控程式設計大賽」,個人參賽者組得獎作品可奪得多點觸控筆記型電腦。

活動網址「Windows 7 多點觸控程式設計大賽」http://w7contest.dotblogs.com.tw/competition.aspx
開發者可以從 http://msdn.microsoft.com/zh-tw/windows/default.aspx 取得相關的技術文件。

不過比較讓我感興趣的是,其中有介紹如何透過模擬方式在Vista上透過滑鼠模擬多點觸控,挺有趣的,相信有不少人需要,提供大家參考。

Silverlight 3 中的multi-Touch程式開發

TechDays 2009忙完了,終於有一點點時間可以回頭寫SL3中的多點觸控,隨著Windows 7的Launch在即,我開始屢屢被問到Silverlight 3中的多點觸控程式開發的部分。

在TechDays 2009中也稍微提過,其實SL3中的多點觸控一點也不複雜,架構上相當簡單,底下這是SL3中多點觸控的訊息架構:

從這邊您也不難發現,觸控螢幕(或面板或NB)、Windows 7、IE8當然都是必要設備,缺一不可。

對於SL3應用程式來說,只是很簡單的從IE8接受多點觸控事件,或者是模擬成滑鼠事件。至於很多人關心的可以接收到幾點,端看設備而定,如果設備傳入的是兩點(我手上的觸控螢幕和NB都只支援兩點),傳入SL3的就是兩點;若設備支援多點,SL3就接收到多點,如此而已,沒啥特別的。

要在SL3當中接收到多點觸控的信息,再簡單也不過,最簡單的方式如下,動作只有兩動:
1.Hook Multi-Touch事件
2.在事件中取得點,進行處理或運算。
程式碼如下:

public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
//Hook事件
Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
}

void Touch_FrameReported(object sender, TouchFrameEventArgs e)
{
//取得點數
int n = e.GetTouchPoints(this.LayoutRoot).Count;
this.textBlock1.Text = "points : " + n;
//將每一點座標顯示出來
foreach (System.Windows.Input.TouchPoint p in e.GetTouchPoints(this.LayoutRoot))
{
this.textBlock1.Text += " \n(" + p.Position.X.ToString("0.00") + "," + p.Position.Y.ToString("0.00") + ") - " + p.Action.ToString();
}
}
}

執行結果:

[範例]

BTW, 這一次範例變成C#了,因為好多人問我要C#的code或是書,因應目前VB/C#還是差不多55波的趨勢,我也不知道到底要寫C#還是VB來的好,總之就隨興寫了,大家就勉為其難和我一起培養 '雙語' 的能力。畢竟這雙語也是一種趨勢嘛...