2011年9月27日 星期二

Silverlight學前研讀心得(二)

最近一兩週的研讀,初步接觸的訊息是,WPF是繼Window Form之後的下一代Windows核心技術,,他很強,在GUI的呈現效果與過往有顯著的不同,如同Win7跟XP的落差,但是,很多企業並不重視這個,「客戶要的需求達到就好了,作這麼漂亮幹嘛?會讓公司多賺個幾百萬嗎?」,我想很多老闆跟主管有這樣的想法並不意外,所以WPF並沒有受到廣泛的使用,(雖然Apple已經讓不少人明白好的使用者介面有多麼讓人喜歡,好的外觀有多麼吸引人,使用者感受對於產品的影響應該是不低的,但是,既然業界沒有這樣的想法,我們工程師也沒輒,所以一、兩個人研發產品介面,一個人獨立作一兩個月把東西作出來,在業界好像還是常態)


Silverlight則是WPF下一個階段的產品,他是WPF的子集合,利用新的開發機制,讓程式設計師可以用習慣的語言(VB或C#或其他)來撰寫Server端程式,然後用Html, Xml類似的TAG語法來撰寫介面(這點跟WPF一樣),然後前端的頁面又可以跟後端的程式溝通,透過WCF的中間服務蠻容易的達成。而這一切僅需要透過VisualStudio就可以做到(介面設計的部分,VisualStudio有內建一個Expression Blend用來設計介面與動畫特效,這個軟體說實在的跟Flash有類似)。然而,一樣的,在台灣Silverlight似乎還沒有很風行,業界用的少,大部分的人還是以Flash搭配Java Script或是用Ajax或是PHP等等,所以連書籍也非常的少,不到10本,很少書局可以看到Silverlight的書,這時候學習這兩個程式開發工具會不會太過冒險了呢?我想,有微軟當靠山,應該還挺穩的,只是時間的問題,多久之後才會贏過Flash,多久之後才能大幅提高佔有率,可以跟C#或C++匹敵呢?不知道,不過,這也代表競爭的人少,有些公司有這樣的職缺,我們要是很熟,很多人又不會,基本上這就是一種優勢了吧。

2011年9月26日 星期一

Silverlight學前研讀心得(一)

上個禮拜,花了蠻多時間研讀WPF的書,不過因為是很紮實的書籍,從基礎開始學習,並且一個範例一個範例的敲出程式,然後跑測試看看,這樣的學習時間,應該會拉的蠻長的沒錯,樂觀的看,沒有一個月以上,應該沒辦法學完整本。然後,很臨時的收到任務,我要接下Silverlight開發的產品,所以這個研讀就暫時先把比重放低,甚至先暫停也可能。








這個禮拜,幾乎都在研讀Silverlight的書,一開始看兩本章立民先生的書,【Silverlight2.0精華技術手冊-使用VC#】,以及【Silverlight3.0全面精通手冊】,這兩本書,很巧的,有好多篇幅都差不多,可能其中一本是另外一本的延續書嗎?不知道。其中的第二章跟第三章的內容:「應用程式的建置、執行、快取、分割」非常的生硬,但是對我來說,我又是非常的想要正確的學習這些基礎的知識,(註一),但是這兩本書幾乎是把MSDN網頁的內容照抄下來,什麼程式庫組件,應用程式組件,類別庫組件,..........名詞難懂就算了,這個還好,很多書都這樣,但他描述的語句生硬,難懂死了,感覺教科書都沒這麼難理解。可能是我的閱讀能力有問題也不一定。但是看這兩本書真的讓人覺得很挫折,覺得Silverlight是不是真的就這麼困難啊?還是我真的太爛了,僅學過ASP的我,學不會這高深的技巧呢?









還好還有另外一本書可以翻一下,董大偉先生的【Silverlight範例權威講座】這本閱讀起來輕鬆多了,因為是自撰書,用的詞句很白話,不但聽得懂,照著引導,很清楚的知道怎麼做出一個簡單的Silverlight的網頁程式,讓我重拾信心,不過可惜的是這本書後來以VB為主,C#的部分要自己摸索,而且這本書使用的版本是Silverlight2.0,我上網找了,新版的書籍是3.0而已,而且不論2.0這本或3.0這本都絕版了。好吧,或許他正在寫4.0的書,我等等看好了,因為我在書局翻了另外兩本書,感覺內容還蠻不錯的樣子。






這兩本就是【Silverlight 4 商業級應用程式開發】與【銀光誌—Silverlight 3.0 實例開發應用】,第一本,是翻譯書,用詞遣字方面沒有這麼好,但是至少可能因為原文寫的還挺淺顯的,所以翻譯的內容看起來似乎沒這麼難懂,且內容是4.0是目前少數僅有的新書了,另外一本,感覺是作者自撰書,所以內容看起來也蠻好懂,我想,就先用這兩本書當我入門書好了,希望能順利的學會這個新技能。










註一:
因為我想要能夠學習到這個Silverlight2.0完整的知識,這是我學習新東西的習慣,我喜歡把一個東西從基礎細節學好,再到延伸應用。從要怎麼開始一個專案,要怎麼根據需求規劃來切割我的程式,在方案總管看到的那些檔案,各自有什麼用途,我需要注意什麼設定,才能達到什麼需求,這些都是沒有學好的話,對我來說,寫出來的東西只是半桶水,只是容易不穩定的實驗品,因為不懂這些基礎,你對程式的掌握度會不夠,有時候出了一些BUG卻改不動,有時候,比方因為模組切割的不恰當,會導致程式效能不佳或是衍生很多撰寫上的困難,諸如此類的,讓我很重視程式開發工具的架構學習。

2011年9月20日 星期二

Silverlight第二章

Silverlight應用程式最終會被建置成一個應用程式封裝檔:(.xap),並存放於ClientBin目錄中。我們會在網頁中用<object>標記來指定所要執行的Silverlight應用程式封裝檔,這樣當此網頁被瀏覽器開啟時,就會下載並執行所指定的xap檔

2011年9月19日 星期一

WPF第一章

1.一個應用當中只能有一個Application物件,這個物件是看不見的,不像Window物件,看得到視窗,有標題列。

2.建立Window物件跟Application物件的順序沒有一定,只有一些原則要遵守,Application的Run必須保留在最後,因為Run方法一旦被呼叫就不會返回,直到視窗被關閉結束。

3.可以不要呼叫Window的Show方法而是直接把Window物件當作參數傳遞給Run方法,這樣Run方法會去呼叫Window物件的Show方法的。

4.Application類別具有一個Static Property名為Current,裡頭包含一個MainWindow物件,這個取用方式有個注意事項,宣告產生Application物件必須在宣告產生Windows物件之前完成,或是呼叫Run的時候傳入的Window物件,否則會得到Null reference exception。Current裡頭也包含著Windows的Collection類別,可以透過他取得所有的

5.Application類別具有數個有用的事件,大多數的事件都有對應的Protected方法可以發出事件,例如Startup事件是利用OnStartup方法所產生。當呼叫Application的Run()之後,就會立刻呼叫OnStartup方法,當Run返回時,則會立刻呼叫OnExit(),可以用這些事件的時機來作應用程式的初始化跟清除。

6.一個程式可以有多個視窗

2011年9月13日 星期二

什麼是WPF

開始年份
語言
介面
1985
C
Windows API
1992
C++
MFC程式庫
2001
C#C++
Windows Form
2006
C#C++
Windows Presentation Foundation


從最開始的Windows程式只能利用C語言以及Windows API,到過去幾年,開始出現最多人使用的的MFC程式庫,之後演進到受管控的(Managed Code)現代化的NETWindows Form設計方式,這幾年則出現WPF這個新一代的設計方案。

WPF在繪圖、動態效果卓越提升,除了2D,還支援3D的效果。除了用程式語言C#開發,也能用XMAL語法來開發,新一代的Silver Light就是延續著WPF而精簡出來的新一代網頁開發工具。

2011年9月9日 星期五

C#如何引用dll

如果是很單純的要呼叫C#的dll
只要[專案][加入][參考 ],把dll加入之後




[DllImport("yyyyyy.dll")]
public extern static void gggggg();
yyyyyy表示該dll的檔名
gggggg表示要呼叫的函式名稱


最後,在你想呼叫該函式的地方:
xxxxxx.classname.gggggg();即可,其中classname是該function所在的class名稱,因為函式一定要存在於Class當中,且注意,該函式一定要宣告為static才行

ListBox 相關元件對Item或Select的CopyTo差異在哪裡?

List.Item.CopyTo( Object, Index )
此方法不支援 Int 陣列,僅支援 String 與 Object
因為該集合是項目內容,可能為非數字




List.SelectedIndices.CopyTo( Array, Index )
此方法支援 Int 等型態的陣列
因為該集合是項目 Index,一定是數字

2011年9月8日 星期四

C# Background Worker介紹

Background worker:一個簡單、好用的Thread方案
它可以以很簡單的方法產生工作執行緒,並且保持主執行緒的可用性,並且也支援回報狀態與交換資料能力,更方便的是他在處理跨執行緒使用UI介面的部分,大多時候可以不用透過Delegate、Invoke、WaitCallBack......等等複雜的觀念與機制,因為他已經幫你實作掉了。




寫法:可以由工具箱當中直接拉Background worker的控制項到Form上面,這樣也可以直接雙擊IDE介面來產生事件Method。


或是也可以自己宣告來產生實體,自己設定Event物件與Event Method。








Method:
RunWorkerAsync(object)
呼叫此函式,會讓Background worker以多執行緒的方式來執行DoWork()內的程式




DoWork(object sender, DoWorkEventArgs e)
將你想執行的耗時的程式片段寫在其中,在呼叫Background worker的RunWorkeAsync()時,就會以多執行緒的方式執行此函式。注意,在這個函式中,可以執行任何跟UI有關的動作,不允許跨執行緒存取UI。




RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
當DoWork()被執行完成之後,會自動呼叫這個函式,如果預期完成之後要做什麼動作,可以寫在這個函式裡。這個函式可以存取Main Thread的UI,不會有誇執行緒的問題。或者說,除非寫法上有多執行緒的特殊用法,否則一般來說這個函式會在Main Thread執行,也因此才不會有跨執行緒存取UI的問題產生。





ProgressChanged(object sender, ProgressChangedEventArgs e)
Background worker提供了一個ReportProgress()的函式,可以隨時對這個背景執行的工作定義完成進度,而通常,想當然爾,這個函式,會在DoWrok裡呼叫,依照做的進度,來呼叫函式傳給Background worker,而當你呼叫了ReportProgress()之後,就會立刻一併觸發ProgressChanged()。而這個函式可以存取Main Thread的UI,不會有誇執行緒的問題。或者說,除非寫法上有多執行緒的特殊用法,否則一般來說這個函式會在Main Thread執行,也因此才不會有跨執行緒存取UI的問題產生。 也就是說,一般我們會把需要變更UI的程式寫在這裡,而不會寫在DoWork(),當DoWrok()當中的,需要對UI有什麼控制時,就以回報進度的方式,在ProgressChanged()裡頭來做。

ListView 的使用教學

  • ListView的屬性View有五種設定值,分別是LargeIcon、Details、SmallIcon、List、Tile,代表著五種不同的資料檢視模式


  • Item屬性可以編輯項目,這些項目,就是會呈現在ListView上的所有項目,當你以Details以外的模式查看資料就可以看到這些項目了。但是,此時在檢視模式「Details」看則是空白。


  • 如何在Detail模式下可以看到資料呢?你必須編輯Columns屬性,只要新增一個Column,就能顯示出這些項目了。


  • 如果再新增Columns,會發現,不會顯示多的資料出來,後面幾欄都會是空的,必須編輯Items的SubItems屬性,這個項目會對於剛剛的Items屬性增加細節資訊,這些細節資訊,會對應到兩種顯示模式,分別是Details跟Tile,對於Details,則是看Columns的數量,如果Columns的數量夠多才能將細節資訊顯示出來而對於Tile,增加的資訊,會列在主資訊旁邊,有點像是註解般的,但是要注意的是,Columns屬性還會影響檢視模式「Tile」的顯示,Columns有幾個,這邊才會把每個Items的第幾個SubItems顯示出來的

  • 而群組屬性則是可以將所有的Items分成幾個不同的群組來顯示資料,編輯Groups屬性時會發現你無論新增幾個Groups,對畫面的影響僅有畫面多了一個Default的標題,所有項目都被放在Default標題之下。接下來要做的動作是到Items的屬性設定畫面,將Group屬性選擇成剛剛建立的Group,凡是沒有指定的都會放在Default那個區塊底下的

  • 還可以放入ImageList元件,將圖片設定好,就可以在ListView的LargeImageList與SmallImageList屬性設定到ImageList元件,這樣在檢視模式:「LargeIcon」就可以看到大圖示,而其他的模式則可以看到指定小圖。

字串格式與對齊解說(三)數值篇

String.Format( String, Object )的使用方式有點類似之前C的printf()
舉例來看:

ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",123,60);
ReadAmount = 123;
ResultStr = String.Format( "謝謝您在{1:##}分鐘內閱讀本文章第 {0:00###} 次了.",ReadAmount,60 );
這樣的語法,就能得到 ResultStr = "謝謝您在60分鐘內閱讀本文章第00123次了。也就是說,可以傳入由字串格式項目與參數的組合來達到串出所需字串的目的,而在 { } 兩個大括弧中間的,就是控制格式化的部分,而大刮號之間的第一個數字,是表示要用後面所給的第幾個參數,通常會是需要被格式化的「數字、時間、.....等等格式」,比方,以第二個例子來說,就會拿後面的參數60代到前面的{1}那邊,而參數ReadAmount則是會被代到前面的{0}的地方而 : 符號後面的部分,則是可以用很複雜的控制代碼,控制代碼,分成很多種。

我們先看常用的標準的格式代碼(格式碼通常不用在意大小寫,都適用)
----------------------------------------------------------------------------------------------
C 表示貨幣,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前NumberFormatInfo物件所提供的預設貨幣精確度。 
例如:String.Format( "{0:C5}", 12345.678901234 )則會得到NT$12,345.67890  
 
D 表示十進位(只支援整數型別),並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零
例如:String.Format( "{0:D8}", 12345 )則會得到00012345 
 
E 表示科學符號,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
 

F 表示浮點數,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:F3}", 12345.678901234 )則會得到12345.679
 

G 表示一般,並且可接著一個數字,來並且可接著一個數字,來表示要顯示多少位數(包含整數與小數的部分),而可能轉為科學記號,也可能轉出浮點數,(說明文件說會挑以最精簡顯示方式來顯示,但很難懂),直接看範例
例如:String.Format( "{0:G3}", 12345.678901234 )則會得到123e+04
例如:String.Format( "{0:G4}", 12345.678901234 )則會得到1235e+04
例如:String.Format( "{0:G5}", 12345.678901234 )則會得到12346
例如:String.Format( "{0:G6}", 12345.678901234 )則會得到12345.7


N 表示數字,並且可接著一個數字,表示要的精度到小數第幾位,不接數字則會使用目前 NumberFormatInfo 物件的 NumberDecimalDigits 屬性所提供的預設數值精確度。
例如:String.Format( "{0:N3}", 12345.678901234 )則會得到12345.679
 

P 表示百分比,並且可接著一個數字,來表示要的精度到小數第幾位,不接數字則預設六位小數
例如:String.Format( "{0:E}", 12345.678901234 )則會得到1.234568E+004
 

X 表示16進位,並且可接著一個數字,來表示要顯示多少位數,不夠的部分會於左邊補零。這個X的大小寫,有意義,會指定輸出的16進位的英文部分要大寫還是小寫。
例如:String.Format( "{0:X8}", 123456 )則會得到0001E240



我們再看常用的自訂的格式代碼
----------------------------------------------------------------------------------------------
0 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,會補零。
# 的用法是會讓轉出來的字串被數字取代,但是如果沒數字的地方,不會有數字。
. 的用法是決定轉出的字串的小數點對齊位置。
\ 的用法是讓這些保留控制碼也可以被顯示出來。
其他符號都會直接被顯示在轉出的字串裡


例如:
String.Format( "{0:000000}", 1234 )則會得到001234
String.Format( "{0:000.000}", 1234.56 )則會得到1234.560
String.Format( "{0:######}", 1234.56 )則會得到1234
String.Format( "{0:###.###}", 1234.56 )則會得到1234.56
String.Format( "{0:###.000}", 1234.56 )則會得到1234.560




補充PadLft與PadRight

字串格式與對齊解說(二)時間篇


標準的日期時間格式如下表


格式
說明
指令
輸出
"d"
簡短日期模式。
String.Format( "{0:d}", TheDateTime );
2009/6/15
"D"
完整日期模式。
String.Format( "{0:D}", TheDateTime );
2009615
"f"
完整日期/時間模式 (簡短時間)
String.Format( "{0:f}", TheDateTime );
2009615 下午 01:45
"F"
完整日期/時間模式 (完整時間)
String.Format( "{0:F}", TheDateTime );
2009615 下午 01:45:30
"g"
一般日期/時間模式 (簡短時間)
String.Format( "{0:g}", TheDateTime );
2009/6/15 下午 01:45
"G"
一般日期/時間模式 (完整時間)
String.Format( "{0:G}", TheDateTime );
2009/6/15 下午 01:45:30
"M""m"
/日模式。
String.Format( "{0:m}", TheDateTime );
615
"O""o"
來回日期/時間模式。
String.Format( "{0:o}", TheDateTime );
2009-06-15T13:45:30.0000000
"R"”r"
RFC1123 模式。
String.Format( "{0:r}", TheDateTime );
Mon, 15 Jun 2009 13:45:30 GMT
"s"
可排序日期/時間模式。
String.Format( "{0:s}", TheDateTime );
2009-06-15T13:45:30
"t"
簡短時間模式。
String.Format( "{0:t}", TheDateTime );
下午 01:45
"T"
完整時間模式。
String.Format( "{0:T}", TheDateTime );
下午 01:45:30
"u"
國際可排序日期/時間模式。
String.Format( "{0:u}", TheDateTime );
2009-06-15 13:45:30Z
"U"
國際完整日期/時間模式。
String.Format( "{0:U}", TheDateTime );
2009615 上午 05:45:30
"Y""y"
年月模式。
String.Format( "{0:y}", TheDateTime );
20096



自訂的日期格式時間如下

格式規範
說明
指令
輸出
"d"
月份的日期,從 1 31
Console.WriteLine( String.Format( "{0:d }", dd ) );
15
"dd"
月份的日期,從 01 31
Console.WriteLine( String.Format( "{0:dd }", dd ) );
15
"ddd"
一週中星期幾的縮寫名稱。
Console.WriteLine( String.Format( "{0:ddd }", dd ) );
星期一
"dddd"
一週中星期幾的完整名稱。
Console.WriteLine( String.Format( "{0:dddd }", dd ) );
星期一
"f"
日期和時間值中的秒數小數點後一位。
Console.WriteLine( String.Format( "{0:f }", dd ) );
0
"ff"
日期和時間值中的秒數小數點後兩位。
Console.WriteLine( String.Format( "{0:ff }", dd ) );
00
"fff"
日期和時間值中的秒數小數點後三位。
Console.WriteLine( String.Format( "{0:fff }", dd ) );
000
"ffff"
日期和時間值中的秒數小數點後四位。
Console.WriteLine( String.Format( "{0:ffff }", dd ) );
0001
"fffff"
日期和時間值中的秒數小數點後五位。
Console.WriteLine( String.Format( "{0:fffff }", dd ) );
00012
"ffffff"
日期和時間值中的秒數小數點後六位。
Console.WriteLine( String.Format( "{0:ffffff }", dd ) );
000123
"fffffff"
日期和時間值中的秒數小數點後七位。
Console.WriteLine( String.Format( "{0:fffffff }", dd ) );
0001234
"F"
日期和時間值中的秒數小數點後一位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:F }", dd ) );
"FF"
日期和時間值中的秒數小數點後兩位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FF }", dd ) );
"FFF"
日期和時間值中的秒數小數點後三位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFF}", dd ) );
"FFFF"
日期和時間值中的秒數小數點後四位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFF }", dd ) );
0001
"FFFFF"
日期和時間值中的秒數小數點後五位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFF }", dd ) );
00012
"FFFFFF"
日期和時間值中的秒數小數點後六位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFFF }", dd ) );
000123
"FFFFFFF"
日期和時間值中的秒數小數點後七位。但如果此精密度內為零,則不顯示。
Console.WriteLine( String.Format( "{0:FFFFFFF }", dd ) );
0001234
"g""gg"
時期或時代。
Console.WriteLine( String.Format( "{0:g }", dd ) );
西元
"h"
小時,使用從 0 11 12 小時制。
Console.WriteLine( String.Format( "{0:h }", dd ) );
1
"hh"
小時,使用從 00 11 12 小時制。
Console.WriteLine( String.Format( "{0:hh }", dd ) );
01
"H"
小時,使用從 0 23 24 小時制。
Console.WriteLine( String.Format( "{0:H }", dd ) );
1
"HH"
小時,使用從 00 23 24 小時制。
Console.WriteLine( String.Format( "{0:HH }", dd ) );
01
"K"
時區資訊。
Console.WriteLine( String.Format( "{0:k }", dd ) );
k
"m"
分鐘,從 0 59
Console.WriteLine( String.Format( "{0:m }", dd ) );
8
"mm"
分鐘,從 00 59
Console.WriteLine( String.Format( "{0:mm }", dd ) );
08
"M"
月份,從 1 12
Console.WriteLine( String.Format( "{0:M }", dd ) );
6
"MM"
月份,從 01 12
Console.WriteLine( String.Format( "{0:MM }", dd ) );
06
"MMM"
月份的縮寫名稱。
Console.WriteLine( String.Format( "{0:MMM }", dd ) );
六月
"MMMM"
月份的完整名稱。
Console.WriteLine( String.Format( "{0:MMMM }", dd ) );
六月
"s"
秒數,從 0 59
Console.WriteLine( String.Format( "{0:s }", dd ) );
9
"ss"
秒數,從 00 59
Console.WriteLine( String.Format( "{0:ss }", dd ) );
09
"t"
AM/PM 指示項的第一個字元。
Console.WriteLine( String.Format( "{0:t }", dd ) );
"tt"
AM/PM 指示項。
Console.WriteLine( String.Format( "{0:tt }", dd ) );
上午
"y"
年份,從 0 99
Console.WriteLine( String.Format( "{0:y }", dd ) );
9
"yy"
年份,從 00 99
Console.WriteLine( String.Format( "{0:yy }", dd ) );
09
"yyy"
年份,至少有三位數。
Console.WriteLine( String.Format( "{0:yyy }", dd ) );
2009
"yyyy"
年份,四位數的數字。
Console.WriteLine( String.Format( "{0:yyyy }", dd ) );
2009
"yyyyy"
年份,五位數的數字。
Console.WriteLine( String.Format( "{0:yyyyy }", dd ) );
02009
"z"
UTC 之間的小時時差,若前置字元為零則去掉該字元。
Console.WriteLine( String.Format( "{0:z }", dd ) );
+8
"zz"
UTC 之間的小時時差,若差異值為個位數則前置字元為零。
Console.WriteLine( String.Format( "{0:zz }", dd ) );
+08
"zzz"
UTC 之間的小時和分鐘時差。
Console.WriteLine( String.Format( "{0:zzz }", dd ) );
+08:00