Silverlight 2 Tutorial – Kết nối mạng để lấy dữ liệu vào một DataGrid.


Đây là phần ba của loạt 8 bài hướng dẫn cách xây dựng một chương trình Digg đơn giản sử dụng bản Beta1 của Silverlight 2. Các bài hướng dẫn này nên được đọc theo thứ tự, và giúp giải thích một số khái niệm nền tảng của Silverlight.

Dùng mạng để lấy dữ liệu từ Digg
Silverlight cung cấp một tập API cho phép các chương trình có thể gọi các dịch vụ từ xa như REST, SOAP/WS*, RSS, JSON và XML HTTP. Silverlight 2 cũng bao gồm một tập API dùng cho socket (System.Net.Sockets) cho phép giao tiếp bằng các giao thức không dựa trên HTTP (chẳng hạn như các chat server…).

Truy cập vào các domain khác
Các chương trình Silverlight 2 luôn có thể truy cập vào máy chủ mà nó đã được tải xuống. Silverlight 2 cũng có thể truy cập vào các máy chủ ở tên miền khác nếu (cross-domain) trên máy chủ đó có chứa một file (dạng XML) chỉ ra các máy trạm được phép tạo ra các lời gọi cross-domain đến nó.
Silverlight 2 định nghĩa một định dạng file chứa các policy cho phép người quản trị máy chủ có thể kiểm soát được các lời gọi đến nó. Và định dạng mà nó dùng cũng chính là định dạng mà Flash dùng, do vậy bạn hoàn toàn có thể dùng Silverlight 2 để gọi đến các dịch vụ REST, SOAP/WS*, RSS, JSON hay XML sẵn có trên web nếu nó đã được cấu hình cho phép các chương trình Flash truy cập vào.
Digg.com cung cấp một tập hàm API khá hay mà bạn có thể truy cập được thông qua HTTP. Bởi vì họ có một file cross-domain policy đặt trên server, do vậy có thể gọi đến chúng thông qua chương trình Digg của chúng ta (Bạn có thể xem file này tại đây), và nó không bắt buộc chúng ta phải gọi ngược lên server để truy cập vào các chức năng này.

Tập hàm API của Digg.com
Chúng ta cho phép người dùng gõ vào một chủ đề nào đó để tìm kiếm (ví dụ: “Programming”) và nhấn nút “Search” để lấy về nội dung khớp với từ khóa đó từ Digg.com.

Chúng ta có thể dùng tập hàm API “List Stories REST API” của Digg.com để làm điều này, nó nhận vào một tham số là chủ đề cần tìm trên URL (ví dụ: GET /stories/topic/programming), và trả ngược lại kết quả dạng XML của chủ đề được tìm kiếm. Bạn có thể nhấn vào đây để xem kết quả của phép tìm kiếm này.

Dùng System.Net.WebClient để thực hiện lời gọi không đồng bộ đến Digg REST Feed
Khi nút Search ở trên được nhấn, chúng ta sẽ bắt được sự kiện “CLick”, lấy chuỗi chủ đề tìm kiếm trong ô văn bản có kiểu WaterMarkTextBox, khở tạo lời gọi qua mạng đến Digg để nhận về chuỗi XML chứa kết quả tìm kiếm cho chủ đề trên.
Silverlight cũng bao gồm lớp WebClient bên trong namespace System.Net (giống cái có trong bộ .NET Framework đầy đủ). Chúng ta có thể dùng lớp này để tải về kết quả một cách không đồng bộ từ một URL. Ưu điểm của việc tải về không đồng bộ là chương trình chúng ta sẽ không bị khóa hay không phản hồi khi chúng đang chờ dữ liệu về từ máy chủ.
Tất cả những gì cần làm để thực hiện một lời gọi không đồng bộ với lớp WebClient là đăng ký một hàm xử lý sự kiện “DownloadStringCompleted” (hàm này sẽ được gọi khi nội dung yêu cầu đã được tải về), và gọi hàm WebClient.DownloadStringAsync(url) để bắt đầu việc download:

Với đoạn mã ở trên chúng ta có thể lấy về một chuỗi dạng XML chứa kết quả tìm kiếm của Digg.com.

Dùng LINQ để phân tích chuỗi XML trả về bởi Digg.com để đưa vào lớp Story
Bay giờ chúng ta đã có thể lấy về chuỗi XML kết quả, bước tiếp theo là phân tích và chuyển nó thành các dối tượng “DiggStory” để có thể được xử lý và gắn nối vào các control của chúng ta.
Bước đầu tiên để làm điều này là định nghĩa một lớp “DiggStory” có chứa các thuộc tính khớp với nội dung của chuỗi XML trả về bởi Digg (chúng ta sẽ tận dụng ưu điểm của một tính năng mới trong C# là “automatic properties” để làm điều này).

Sau đó có thể dùng LINQ (có sẵn trong Silverlight 2) và LINQ to XML (là một thư viện mở rộng mà chúng ta có thể gắn thêm vào chương trình Silverlight của chúng ta) để dễ dàng phân tích và lọc tài liệu XML được trả về từ Digg, và dịch nó thành một chuỗi các đối tượng DiggStory dùng đoạn mã dưới đây:

Chú ý rằng ở trên chúng ta đã có các đối tượng DiggStory thực sự.

Hiển thị dữ liệu của Digg trong một DataGrid
Chúng ta sẽ dùng một control mới trong Silverlight là DataGrid để hiển thị dữ liệu Digg. Để cho phép điều này, chúng ta sẽ phải tham chiếu đến assembly chứa Silverlight Data control, và thay thế đoạn “Todo” trước đây với một khai báo DataGrid:

DataGrid cho phép bạn khai báo cụ thể các cột cùng với kiểu hiển thị của nó (để có thể kiểm soát một cách tối đa). Cách khác, bạn có thể đặt thuộc tính “AutoGenerateColumns” bằng True để yêu cầu DataGrid tự động tạo ra các cột dựa trên cấu trúc của các đối tượng của bạn.
Chúng ta cũng sẽ cập nhật lại lớp code-behind để gắn thuộc tính ItemSource của DataGrid và chuỗi các đối tượng mà chúng ta đã lấy được khi gọi hàm của Digg mỗi khi nút Search được nhấn.

Bây giờ, mỗi khi chúng ta chạy chương trình Silverlight và thực hiện việc tìm kiếm, chúng ta sẽ thấy một danh sách các chủ đề lấy về từ Digg:

DataGrid trong Silverlight hỗ trợ tất cả các tính năng bạn mong muốn với một control chạy trên máy trạm: cho phép sửa chữa dữ liệu 2 chiều, chọn, cuộn, thay đổi chiều rộng cột… Nó cũng hỗ trợ auto-flow layout, cho phép tự động mở rộng hay thu hẹp để vừa với đối tượng chứa nó. DataGrid cũng hỗ trợ các mẫu cho phép tùy biến cả về cách định dạng cũng như cách chỉnh sửa dữ liệu. Tôi sẽ viết thêm các bài viết khác về cách dùng DataGrid.

Bước tiếp theo
Giờ chúng ta đã có thể lấy dữ liệu từ Digg.com và hiển thị nó lên cửa sổ ứng dụng.
Bước kế tiếp chúng ta sẽ quay trở lại trang Page.xaml và bỏ đi các khai bảo định dạng trực tiếp mà chúng ta đang dùng.
Để làm điều này, xin mời bạn đọc bài tiếp theo: Xây dựng giao diện dùng Style.

11 thoughts on “Silverlight 2 Tutorial – Kết nối mạng để lấy dữ liệu vào một DataGrid.

  1. Sub DisplayStories(ByVal xmlContent As String)
    Dim xmlStories As XDocument = XDocument.Parse(xmlContent)
    Dim Stories = From Story In xmlStories.Descendants(“Story”) _
    Where Story.Element(“thumbnail”) IsNot Nothing AndAlso (Not Story.Element(“thumbnail”).Attribute(“src”).Value.EndsWith(“.gif”)) _
    Select new DiggStory With {.Id = CInt(Fix(Story.Attribute(“id”).Value)), .Title = (CStr(Story.Element(“title”))).Trim(), .Description = (CStr(Story.Element(“description”))).Trim(), .ThumbNail = CStr(Story.Element(“thumbnail”).Attribute(“src”).Value), .HrefLink = New Uri(CStr(Story.Attribute(“link”).Value)), .NumDiggs = CInt(Fix(Story.Attribute(“diggs”).Value)), .UserName = CStr(Story.Element(“user”).Attribute(“name”).Value)}
    End Sub

    Bien DiggStory co can khai bao khong vay anh? Em viet nhu anh nhung no bao loi la chua khai bao bien DiggStory?

  2. thanks anh Nam nhiều lắm. Em (DiggSample.DiggStory) có ảnh hưởng gì không a?

  3. DiggStory là cấu trúc dữ liệu được dùng lưu kết quả lấy từ XML nên tất nhiên em phải cần tới nó.

  4. Cho em hỏi: trong trường anh dùng file xml để lấy dữ liệu thì dùng LinqToXml nhưng nếu em muốn đổ Data vào datagrid mà dùng dataservice hỗ trợ Entities anh có thể demo hoặc hướng dẫn được ko anh, e đã thử nhưng datagride khi e dung ToList() thì báo lỗi, anh có thể mail cho e ko? Thanks anh nhiều nhiều

  5. Tôi làm và chạy thử theo sample của bạn thì gặp lỗi sau.
    Vì mới học nên ko biết giải quyết thế nào, bạn nào biết chỉ cho tôi với.
    ———–
    StackTrace ” at System.ComponentModel.AsyncCompletedEventArgs.RaiseExceptionIfNecessary()\r\n at System.Net.DownloadStringCompletedEventArgs.get_Result()” string

    Message “An exception occurred during the operation, making the result invalid. Check InnerException for exception details.” string
    + InnerException

    {System.Security.SecurityException —> System.Security.SecurityException: Security error.
    at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
    at System.Net.Browser.BrowserHttpWebRequest.c__DisplayClass5.b__4(Object sendState)
    at System.Net.Browser.AsyncHelper.c__DisplayClass4.b__1(Object sendState)
    — End of inner exception stack trace —
    at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
    at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
    at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
    at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)} System.Exception {System.Security.SecurityException}

  6. Em đang dùng Silverlight 5 Tutorial VS 2010, nhưng nó không có WaterMarkTextBox em thay thế bằng TextBox khi viết sự kiện thì nó thông báo lỗi: “Error 1 Non-invocable member ‘System.Windows.Controls.TextBox.Text’ cannot be used like a method. E:\Visual Studio 2008\Projects\Hellword\bai2\MainPage.xaml.cs 25 38 bai2

    vậy cho em hỏi là khắc phục lỗi này như thế nào à? Mong nhận được sự trả lời sớm từ anh.

  7. anh Nam ơi, e dùng Silverlight 3 VS 2010 chạy đến diggService_DownloadStringCompleted thì báo lỗi:
    System.Security.SecurityException —> System.Security.SecurityException: Security error.
    at System.Net.Browser.BrowserHttpWebRequest.InternalEndGetResponse(IAsyncResult asyncResult)
    at System.Net.Browser.BrowserHttpWebRequest.c__DisplayClass5.b__4(Object sendState)
    at System.Net.Browser.AsyncHelper.c__DisplayClass2.b__0(Object sendState)
    — End of inner exception stack trace —
    at System.Net.Browser.AsyncHelper.BeginOnUI(SendOrPostCallback beginMethod, Object state)
    at System.Net.Browser.BrowserHttpWebRequest.EndGetResponse(IAsyncResult asyncResult)
    at System.Net.WebClient.GetWebResponse(WebRequest request, IAsyncResult result)
    at System.Net.WebClient.DownloadBitsResponseCallback(IAsyncResult result)
    anh giúp em sửa lỗi với!
    PS: anh delete hộ e cái post trước

Gửi phản hồi

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s