วันพุธที่ 29 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 7 ใช้ Control Template เพื่อแต่งคอนโทรลให้สวยงามขึ้น

(แปลจาก blog ภาษาอังกฤษของ Scottgu ที่นี่)
หากต้องการตัวอย่าง SourceCode ฉบับเต็ม กดที่นี่

คุณสมบัติพิเศษของ Silverlight และ WPF คือ อนุญาติให้เราปรับแก้ หน้าตา ของคอนโทรล ได้อย่างสมบูรณ์
เรามาดูคอนโทรลแรกที่เราจะแก้กัน

ปุ่ม Button
ของเดิม

มีหน้าตา อย่างนี้

ท่านอาจจะแปลกใจว่า Content ของ Button นั้น ไม่จำเป็นต้องเป็นข้อความเสมอไป จริง ๆ เราอาจใส่ออปเจ็กอื่น ๆ ไว้ภายใน (ในแท็ก <Button.Content>) ได้ เช่น

ได้ผลดังนี้


เราอาจใช้คอนโทรลที่เป็นรูปร่าง(Shape) เช่น Ellipse(วงรี) เช่น


ได้ผลดังนี้


ถ้าเราจะเล่นพิเรนท์ ใส่ปฏิทินลงไปในปุ่ม ก็ยังได้ เช่น


การปรับหน้าตาของคอนโทรลด้วย ControlTemplate
ใน WPF และ Silverlight เราสามารถปรับหน้าตาของคอนโทรลได้โดยสิ้นเชิง โดยที่พฤติกรรมของคอนโทรลไม่เปลี่ยนแต่อย่างใด
ตัวอย่างเช่น ถ้าเราต้องการเปลี่ยนปุ่มให้เป็นรูปวงกลมเหมือนด้านล่าง ให้เราสร้าง Style ขึ้นมาอันนึง เก็บไว้ใน App.xaml แล้วใส่ <ControlTemplate> ไว้ข้างใน ภายในให้ใส่ หน้าตา ที่ต้องการไว้
ดังนี้


แล้วนำไปใช้กับ Button ดังนี้

จะได้ผล ดังนี้

แต่ สังเกตว่า ใน Button เรากำหนด Size และ Content ไว้ตายตัว("Push Me!)
แต่ ถ้าเราต้องการจะนำ Size ที่ผู้ใช้คอนโทรลด้านนอก กำหนดมา มาใช้
และใช้ Content ที่ผู้ใช้ด้านนอกกำหนดมา มาใช้

ให้เราใช้ {TemplateBinding}
และใช้ ContentPresenter แทน Content ของเรา ดังนี้

แล้วเรานำ ControlTemplate นี้ไปใช้ ดังนี้


แล้วได้ผลดังนี้

ทีนี้เราจะให้ เป็นปุ่มวงกลม แล้วนำไปใช้ใน Digg ดังนี้

แล้วได้ผลลัพท์สุดท้าย ดังนี้

วันจันทร์ที่ 27 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 6 ใช้ User Control เพื่อแสดงข้อมูลแบบหนึ่งต่อหลาย (Master/Detail)

(แปลจาก blog ภาษาอังกฤษของ Scottgu ที่นี่)
หากต้องการตัวอย่าง SourceCode ฉบับเต็ม กดที่นี่

เป้าหมายพื้นฐานของ Silverlight และ WPF คือ ให้ผู้ใช้สร้างคอนโทรลขึ้นมาเอง ที่จะนำกลับมาใช้ใหม่ได้เรื่อย ๆ โดยเขียน คอนโทรลสืบทอดจากคอนโทรลเดิมที่มีอยู่แล้วใน Silverlight (จาก Control หรือ TextBox , Button ,อื่น ๆ)

สำหรับในตัวอย่างนี้ เราต้องการให้ ผู้ใช้ ค้นหา Topic แล้วแสดง Story ใน List เมื่อผู้ใช้เลือก Story แล้ว จะแสดง Detail ออกมา เช่น ให้เลือก Storyจาก ListBox ด้านล่าง



แล้วจะแสดง Detail ดังนี้


เราจะสร้างคอนโทรล ที่ชื่อว่า "StoryDetailsView" เพื่อแสดงผล Detail ดังภาพด้านบน
โดยกด Add New Item แล้ว เลือก Silverlight User Control แล้วกด Add

จะเกิดไฟล์ 2 ไฟล์ คือ StoryDetailsView.xaml และ StoryDetaisView.xaml.cs ดังนี้


สร้าง Modal Dialog (หน้าต่างที่ต้องทำงานเสร็จจนปิดก่อน จึงจะทำงานอย่างอื่นต่อได้) โดยใช้ User Control

เราจะแสดงภาพให้ดูเหมือน ปิดหน้าเดิม ด้วยการสร้าง สี่เหลี่ยม Rectangle ทึบ ๆ ครอบทับ หน้าจอ ดังนี้

Opacity คือ ความทึบแสง ถ้ามีค่าเป็น 1 หมายถึงทึบ ถ้ามีค่าเป็น 0 หมายถึง ใส
ในที่นี้ Opacity="0.765" หมายถึง ทึบแสง 76.5%
HorizontalAlignment="Stretch" หมายถึง กว้างเต็มตามแนวขวาง
VerticalAlignment="Stretch" หมายถึง สูงเต็มตามแนวตั้ง (พูดง่าย ๆ ว่า เต็มจอ)

Border ด้านล่าง คือ กรอบของไดอะลอก มีมุมมน (CornerRadius="30")
แล้วมี Button ปุ่ม Close อยู่ข้างใน เชื่อมกับอีเวนท์ CloseBtn_Click

ได้ผลดังนี้


ในฟังก์ชัน CloseBtn_Click ที่อยู่ใน .cs ให้กำหนด Visibility ของคอนโทรลให้เป็น Collapsed เพื่อซ่อนปิดคอนโทรลไป ดังนี้


การนำคอนโทรลไปใช้
เราก็ใส่คอนโทรลของเราเข้าไปในหน้า Page.xaml และกำหนด Visibility="Collapse" ไว้ก่อน ดังนี้

ให้เราสร้างฟังก์ชันเชื่อมอีเวนท์ SelectionChanged จาก ListBox ของเรา ดังนี้

ทำให้ เมื่อเราเลือกหัวข้อใดหัวข้อหนึ่งใน ListBox แล้ว คอนโทรลของเราก็จะปรากฏตัวขึ้น

ส่งต่อข้อมูลของ Story ไปให้ คอนโทรลของเรา
เมื่อผู้ใช้เลือก Story ที่ต้องการแล้ว เราก็จะส่ง Story นั้นไปเก็บไว้ในพร้อพเพอตี้ DataContext ของ DetailsView (สำหรับ DataBinding) ดังนี้ แล้วแสดงคอนโทรลออกมา (โดยเซ็ต Visibility) ดังนี้


แล้วในคอนโทรลของเรา เชื่อม (DataBind) ระหว่าง Title กับ TextBlock ดังนี้

จะได้ผลดังนี้

สังเกตว่า Title ของ Story มาแสดงแล้ว
ทีนี้เราจะมาเชื่อมข้อมูล ทั้งหมด แล้วแสดงใน หน้าต่างนี้ ดังนี้

แล้วได้ผล ดังนี้


สังเกตว่า เราสามารถเชื่อม ข้อมูล ระหว่างกัน ผ่านคอนโทรล ด้วยพร้อพเพอตี้ DataContext โดย ไม่ต้องเขียน โค้ดโปรแกรม เลยแม้แต่บรรทัดเดียว

ตอนต่อไป เราจะตกแต่ง ListBox และ Button ให้ดูสวยกว่านี้ ด้วยการแก้ไข ControlTemplate

วันอาทิตย์ที่ 26 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 5 การใช้ ListBox และ Data Binding (เชื่อมโยงข้อมูล)

(แปลจาก blog ภาษาอังกฤษของ Scottguที่นี่)
หากต้องการตัวอย่าง SourceCode ฉบับเต็ม กดที่นี่

ตอนก่อน เราใช้ DataGrid ในแสดงผล ข้อมูลเว็บ Digg ในตอนนี้เราจะลองใช้ ListBox แสดงแทน เพื่อให้ข้อมูลดูเป็นรายการแทน (แทนการดูเป็นตาราง)

เริ่มต้น แทนคอนโทรล DataGrid ด้วยคอนโทรล <ListBox> โดยให้มีชื่อเหมือนเดิมว่า StoriesList :


เมื่อเรารันโปรแกรม แล้วลอง ค้นหา จะได้ผลดังนี้


คุณอาจประหลาดใจว่า คำว่า "DiggSample.DiggStory" มาจากไหน
เนื่องจาก ListBox ไม่รู้จะเอาค่าไหนของ DiggStory มา มันจึงเอามาจากฟังก์ชัน ToString() แทน

ให้เราเพิ่ม DisplayMemberPath="Title" เข้าไป ดังนี้

เราจะได้ผลดังนี้

เนื่องจาก เราต้องการแสดงผลมากกว่าหนึ่งฟิลด์ และเราต้องการจะจัดวางตำแหน่งข้อมูลใหม่ เราจึงสร้าง
<DataTemplate> ขึ้นมาไว้ใน <ListBox.ItemTemplate> แล้วใส่แท็กสำหรับจัดวางข้อมูลไว้ในภายใน
ตัวอย่างเช่น เราจะแสดง Title ,NumDigg ไว้ใน TextBlock ดังนี้

แล้วได้ผลดังนี้


เราลองมาทำในแบบที่ซับซ้อนขึ้นอีกนิดกัน ดังนี้


และใน App.xaml ก็กำหนด Style ไว้ดังนี้


ได้ผลดังนี้


ตอนหน้า จะเกี่ยวกับแสดงข้อมูล แบบหนึ่งต่อหลาย (Master/Details) ครับ

วันเสาร์ที่ 25 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 4 กำหนด Style เพื่อให้สวยงามขึ้น

(แปลจาก blog ภาษาอังกฤษของ Scottgu ที่นี่)
หากต้องการตัวอย่าง SourceCode ฉบับเต็ม กดที่นี่

ใช้แท็ก Style เพื่อกำหนดหน้าตาการแสดงผล
WPF และ Silverlight มีกลไกที่เรียกว่า Style ที่เราสามารถใช้เพื่อเก็บลักษณะ (ค่า Property) ต่าง ๆ ไว้ในที่เดียว (resource) แล้วนำมาใช้ได้บ่อย ๆ เราอาจเก็บ Style ไว้ในไฟล์อื่นก็ได้ เพื่อที่จะเอามา ปั๊มค่า Property ใส่ Control หลาย ๆ อัน ให้มีหน้าตาเหมือนกัน เช่น กำหนดค่า Color,Font,Size,Margin ไว้ใน Style ชื่อหนึ่ง
แล้วเอา Style นี้ ไปใส่ในคอนโทรล หลาย ๆ อัน แล้วจะมี Color,Font,Size,Margin เดียวกันหมด

ในตัวอย่างนี้ เราจะนำเอาค่า Style ไปเก็บไว้ในไฟล์ชื่อ App.xaml ซึ่งจะทำให้เราเอาไปใช้ได้ในทุก ๆ ที่ในโปรแกรม
จากเดิมที่กำหนดค่า Property ต่าง ๆ ไว้ในคอนโทรลนั้น

ก็ให้เราดึงเอา Property ต่าง ๆ มาใส่ไว้ใน Style แทน ดังนี้

โดยเราจะใส่ x:Key="ชื่อสไตล์"(ด้านบน) เพื่อเป็นตัวระบุ ที่จะนำไปใช้ในภายหลัง(ด้านล่าง) ดังนี้

ในที่นี้ เราจะึดึงเอา Property ของคอนโทรลทุกอัน มาเก็บเป็นสไตล์ทั้งหมด
ดังนี้

การนำ Property มาเก็บไว้ใน Style ทำให้โปรแกรมดูโล่งขึ้น โปรแกรมเมอร์ไม่ลายตา จะได้สนใจในสิ่งที่สำคัญมากขึ้น และสไตล์นั้น ยังเอาไปใช้ในที่อื่น ๆ ได้ด้วย

ตอนต่อไป จะเกี่ยวข้องกับคอนโทรล ListBox และ Data Binding (การเชื่อมกับข้อมูล)

วันพฤหัสบดีที่ 23 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 3 ดึงข้อมูลจาก Internet และแสดงผลใน Data Grid

(แปลจาก blog ภาษาอังกฤษของ Scottgu ที่นี่)
ต่อจากตอนที่แล้ว ตอนนี้ เราสร้าง Silverlight ที่นำข้อมูลจากเว็บ Digg มาแสดงผล

Silverlight 2 มี API ภายในที่จะติดต่อกับ Network ได้หลายแบบ เช่น REST, SOAP/WS*, RSS, JSON ,XML HTTP service และ Socket API(System.Net.Socket ทำให้ติดต่อกับเน็ตที่ไม่ใช่ HTTP ได้ด้วย)

การติดต่อข้ามโดเมน(เว็บไซต์)

โดยปกติ Silverlight จะติดต่อได้กับเว็บไซต์ตัวเอง การติดต่อกับเว็บไซต์อื่นได้ก็ต่อเมื่อ เว็บไซต์อื่นนั้นได้มีไฟล์ XML Policy ที่ระบุอนุญาตให้ติดต่อด้วย(เป็นฟอร์แมตของ Silverlight เอง) และสามารถใช้ไฟล์ XML Policy ในฟอร์แมตของ Adobe Flash ได้ด้วย

เว็บไซต์ Digg.com มี API ในแบบของ Http เจ๋ง ๆ ให้เราใช้พอสมควร และเว็บนี้ก็มีไฟล์ XML Policy สำหรับ Flash เราจึงสามารถติดต่อกับเว็บนี้ได้

การดึงเอาหัวข้อเนื้อหา จาก feed ของ เว็บ Digg.com
เราจะสร้างโปรแกรมที่ ให้ผู้ใช้พิมพ์คำคีย์เวิร์ดเพื่อหาข้อมูล (เช่น Programming) แล้วกดปุ่ม Search เพื่อไปดึงเอาหัวข้อข้อมูลมาแสดง

โดยเราจะเรียกใช้ Digg REST Feed API โดยเราจะใส่คีย์เวิร์ด(คำที่จะหา)ลงใน URL (ตัวอย่างเช่น GET /stories/topic/programming) แล้วส่งไป โดยเราจะได้ XML คำตอนกลับมา
ตัวอย่างเช่น http://services.digg.com/stories/topic/programming?count=20&appkey=http%3A%2F%2Fscottgu.com

เรียกใช้ Digg API แบบ REST ด้วย คลาส System.Net.WebClient
ทันทีที่กดปุ่ม Search เราจะเข้า Event "Click" เพื่อไปเอาข้อความใน TextBox แล้วเข้าฟังก์ชันเรียกเน็ต Digg เพื่อดึงเอา XML มาแสดงผล และเนื่องจากการรอข้อมูลกลับมาจะใช้เวลานาน เราจึงใช้วิธีแบบไม่ต้องรอ(Asynchronous) โดยให้คลาส WebClient เรียก event ของเราตอนที่ได้ข้อมูลครบแล้ว ดังนี้


จะโค้ดด้านบน เราจะได้ XML ผลลัพท์อยู่ที่ตัวแปร result ของเมทอด DiggService_DownloadStoriesCommpleted

เราจะเอาข้อมูลใน XML มาเก็บเป็นออปเจ็ก ๆ ในรูปแบบคลาส ดังนี้


โดยใช้ฟีเจอร์ LINQ to XML (Language Intregrate Query) เพื่อแปลงข้อมูลมาใส่ในคลาส DiggStory
ดังนี้


เอาข้อมูลจากคลาส DiggStory มาแสดงใน DataGrid
เราจะใส่คอนโทรล DataGrid ในโปรแกรมของเรา โดยเพิ่ม reference แอสเซมบลี้ "Silverlight Data Controls" และเพิ่มแท็ก ดังนี้

ฟีเจอร์ของ DataGrid อนุญาต ให้คุณระบุคอลัมภ์ , ชนิดตัวแปร และอื่น ๆ ได้โดยละเอียด
แต่ถ้าคุณต้องการความสะดวก คุณก็ระบุเพียง ItemSource = ข้อมูลที่ได้ ก็พอ แล้ว DataGrid จะกำหนดค่าต่าง ๆ โดยอัตโนมัติ
และถ้าคุณต้องการบอกว่า ไม่ให้เลือก select บรรทัดไว้ก่อนล่วงหน้า ก็ระบุ SelectedIndex = -1 ดังนี้


ตอนนี้เราก็ได้โปรแกรม silverlight เสร็จขึ้นมาอีกระดับหนึ่งแล้ว(หาข้อมูลได้ แสดงข้อมูลได้) ดังนี้


ตอนต่อไปจะเป็นอีก การกำหนด Style เพื่อให้หน้าตาสวยงามขึ้น

กดปุ่มนี้ จะดาวโหลด source code โปรแกรมที่เสร็จแล้ว

วันเสาร์ที่ 18 ตุลาคม พ.ศ. 2551

ทำโปรเจ็ก Silverlight ตอนที่ 2 การจัดวางตำแหน่ง

(แปลจาก บล็อกภาษาอังกฤษของ Scottgu ที่นี่)
กดปุ่มนี้จะดาวโหลด sourcecode โปรแกรมที่เสร็จแล้ว

ต่อจากตอนที่แล้ว เราจะมาดูเรื่อง การจัดวางตำแหน่ง หรือ Layout กัน
ทำความเข้าใจเรื่อง การจัดวาง Layout
Silverlight และ WPF ได้ให้ Control ที่จะช่วยโปรแกรมเมอร์จัดวางตำแหน่ง UI ได้อย่างสะดวก โดยจะมีทั้งแบบกำหนดตำแหน่งตายตัว และแบบที่ให้ Layout จัดการให้

Layout ที่ใช้ใน Silverlight 2 ได้แก่
  • Canvas
  • StackPanel
  • Grid
การจัดวางแบบ Canvas
เป็นการจัดวางที่ให้โปรแกรมเมอร์กำหนดตำแหน่งของ Control ที่จะวางบน Canvas ได้อย่างอิสระ โดยกำหนดพิกัด (ตามแนว x,y) ได้
โดยใช้แอตทริบิว Left แทนตำแหน่ง X และ แอตทริบิว Top แทนตำแหน่ง Y
ดังตัวอย่างที่จะใส่ปุ่ม Button 2 ปุ่ม ลงบน Canvas ดังนี้


ซึ่งจะปรากฏผล ดังนี้

Canvas จะมีประโยชน์ในกรณี ที่ Control จะไม่ขยับตำแหน่ง และขนาดไม่เปลี่ยน
แต่เมื่อตำแหน่งหรือขนาดของ Control เปลี่ยน จะทำให้โปรแกรมเมอร์ต้องมาเปลี่ยนพิกัด จัดใหม่ ให้ดูดี
ในกรณีนี้ ควรจะใช้ Layout แบบอื่น ๆ คือ StackPanel หรือ Grid

StackPanel
StackPanel เป็นการจัดวางที่จะวาง Control ที่อยู่ภายใน เรียงเป็นตามแนวเดียวกัน (ตามแนวนอน หรือตามแนวตั้ง) เช่น


จะได้ผลดังนี้


หากเราจะจัดวางเรียงไปตามแนวนอน ให้เราเพิ่มแอตทริบิว Orientation="Horizontal" ดังนี้



ได้ผลดังนี้



การจัดวางแบบ Grid คือการจัดวางแบบตาราง
คือ การจัดวางที่ยืดหยุ่นที่สุด ทำให้วางในตำแหน่งช่องใดก็ได้ในตาราง และมีขนาดได้มากกว่าหนึ่งช่อง
ดังตัวอย่าง จะ สร้างตารางซึ่งมี 3 คอลัม
โดยเราจะประกาศ คอลัมภ์ ไว้ในแท็ก 3 อันไว้ใน
และประกาศ คอลัมภ์ ไว้ในแท็ก 3 อันไว้ใน

หลังจากนั้น จะใส่ <button> ที่บอกตำแหน่งที่จะใส่ไว้ใน Grid ด้วยแอตทริบิว Grid.Column="x" Grid.Row="y" ดังนี้

จะได้ผลดังนี้


นอกจากการระบุพิกัดแบบตายตัว เช่น Height=60 แล้ว
RowDefinition และ ColumnDefinition ยังมีโหมด AutoSize (ปรับขนาดอัตโนมัติ)
เช่น Height="Auto" จะทำให้ความสูงของ Row นั้น ปรับตามขนาดของ Control ที่อยู่ข้างใน
ซึ่งมีประโยชน์มาก

นอกจากนั้น ขนาดยังกำหนดให้เป็นสัดส่วนต่อกันได้ด้วย เช่น
<RowDefinition Height="1*">
<RowDefinition Height="2*">

แถวที่สอง จะมีความหนากว่า แถวแรก สองเท่า

ตัวอย่างการจัดหน้าจอ แบบ Digg(เว็บไซต์ยอดนิยมแห่งหนึ่ง)
เราจะสร้างหน้าจอ ให้เหมือนแบบนี้


โดยเราจะสร้างให้มี Grid 2 แถว ก่อน แถวแรกสูง 40 pixel(จุดสี) แล้วแถวที่สองให้กินที่ที่เหลือทั้งหมด (Height="*")

โดยเพิ่มแอททริบิว ShowGridLines="True" เพื่อให้เห็นเส้นประ บอกตำแหน่ง

แล้วเราก็จะใส่ Grid ลงไปในช่องแถวแรกของ Grid นอก โดยแบ่งเป็น 3 คอลัม ดังนี้

ทำให้เราเห็นการแบ่ง แถวแรกออก ดังนี้


โดยช่องแรก เราจะใส่คอนโทรล <Border> โดยหัวมุมให้ตัดมน รัศมี 10
แล้วใส่ข้อความ <TextBlock> ไว้ข้างในอีกที
ช่องถัดมาใส่ <WatermarkedTextBox>
ช่องถัดมาใส่ปุ่ม <Button>

แล้วในแถวถัดมา ใส่ <TextBlock> ดังนี้

ได้ผลดังนี้



ตอนนี้เรายังจำกัดความกว้างสูงของ หน้า Silverlight ไว้ที่ 600 x 300 อยู่


ทำให้ ถ้าเราถึงหน้าเว็บเพจออกกว้างก็จะเห็น silverligth ไม่เต็มจอ

ให้เราเอาบรรทัด Width="600" Height="300" ออก
ก็จะให้โปรแกรมที่เต็มหน้าจอบราวเซอร์



โปรดติดตามตอนต่อไป