[Windows Phone – Silverlight] Layout with XAML–Basic for Absolute Beginner Part 2 -ListBox


Đây là phần 2 của loạt bài viết Layout with XAML – Basic for Absolute Beginner
Bài 1 ở đây: [Windows Phone – Silverlight] Layout with XAML–Basic for AbsoluteBeginner - Part 1


Như các bạn đã biết, ngoài Stackpanel và Grid ra, XAML còn có 1 control cơ bản khác, đó là ListBox (và GridView, ListView, nếu bạn đang lập trình cho Windows 8 hay các ứng dụng WPF)
Trong phạm vi bài viết này, mình sẽ đề cập tới ListBox cùng cách thiết kế nó trên giao diện.


  1. LISTBOX CONTROL

ListBox control dùng để hiện thị một danh sách các item.
Danh sách này sẽ có một giao diện nhất định, một kiểu dữ liệu nhất định tùy bạn chọn
Ví dụ: "Top 30 video được xem nhiều nhất trên youtube" là một dạng dữ liệu mà ta sẽ dùng ListBox để hiển thị
  1. Các thuộc tính quan trọng


1.1.1 ItemsSource

ItemsSource là nguồn dữ liệu. Listbox này sẽ hiển thị dữ liệu từ đâu?
ItemsSource có thể là một List hoặc một ObservableCollection, ta sẽ nói đến nó ở phần sau

1.1.2 SelectedIndex

Cái tên đã nói lên tất cả. Đây là item đang được chọn trong listbox của bạn. Trong quá trình khởi tạo, giá trị này sẽ là -1
Lưu ý rằng item bắt đầu từ số 0 trở đi. Giả sử bạn có 5 items, thì nó sẽ được đánh số từ 0 tới 4

1.1.3 SelectedItem

Đây lại là một thuộc tính khác. Giá trị của thuộc tínhnày bằng null khi khởi tạo. Và khi người dùng chọn một item nào đó trong listbox, item đó sẽ được phản xạ sang thuộc tính này.
Thuộc tính này có kiểu dữ liệu là Object, khi dùng bạn phải ép kiểu sang kiểu dữ liệu của danh sách

1.1.4 DataConext – ngữ cảnh dữ liệu

DataContext sẽ được dùng trong một số trường hợp advance binding, hiện tại thì bạn chưa cần phải quan tâm tới nó

1.2 Thử nghiệm

Tạo một project Windows Phone
Trong LayoutRootGrid, tạo một Listbox


Chọn thẻ Property khi đang select listbox này


Trong mục Items, bạn thêm mới một số item cho listbox


Sau đó, chọn Listbox Item, rồi nhấn nút Add


Như bạn có thể thấy, một item với index = xuất hiện cùng thuộc tính của nó


Rồi thêm vào content như hình sau:


Nhấn nút chạy thử, và bạn sẽ thấy cách hoạt động của listbox


Bây giờ bạn đã nắm cách thức Listbox hoạt động cơ bản nhất. Ta hãy cùng "Đào sâu" vào thế giới XAML nhé
  1. DataBinding – Phương pháp tuyệt vời để hiển thị dữ liệu

Listbox được dùng nhiều nhất với kỹ thuật DataBinding này (tạm dịch là gắn kết dữ liệu đi)
Kỹ thuật này cho phép bạn hiển thị dữ liệu từ một nguồn nào đó lên trên listbox. Nguồn đó có thể là một List, hoặc một Observable Collection
Nhiều người khi nghĩ tới DataBinding, họ sẽ nghĩ ngay tới mô hình MVVM.
Khoan đã, trong vai một người mới học, hẳn bạn cũng sẽ không biết MVVM là cái gì, mặt mũi nó ra sao.
Vì vậy, hãy tìm hiểu một số khái niệm và cách thức cơ bản trước đã

2.1 Chuẩn bị

Để thực hiện theo bài viết này, bạn cần có các công cụ sau:
Visual Studio, chắc cái này bạn có rồi
ReSharper: hỗ trợ cho bạn tự động hóa các công việc nhàm chán nhưng cần thiết. Lưu ý đây là phần mềm thương mại
Sau khi cài ReSharper, hãy tiếp tục bài viết nhé

2.2 Kiểu dữ liệu

Để gắn dữ liệu lên ListBox, ta cần phải có một "Nguồn dữ liệu", và nguồn dữ liệu đó phải được tạo ra bởi một kiểu dữ liệu nào đó, vì nó là một danh sách các item
Ví dụ: một danh sách các chuỗi, một danh sách các số nguyên
Tuy nhiên, bạn cũng có thể tạo ra kiểu dữ liệu riêng của mình, như kiểu "Danh sách các món ăn"
Vậy tạo ra kiểu dữ liệu như thế nào?
Tạo một Folder mới, đặt tên là Model


Hãy tạo một file class mới trong folder đó với tên gọi DataStructure


Một class DataStructure mới được tạo ra. Bạn có thể xóa nó đi, và bắt đầu định nghĩa cho class riêng của mình


Theo như hình trên, bạn có 3 thuộc tính private. Khoan đã, private không thể truy cập ngoài class, nên ta cần tạo các public property cho chúng
Trước khi tạo các public property, ta nên làm một chuyện khác, đó là khai báo Interface INotifyPropertyChanged
Interface này giúp cho việc binding dữ liệu lên giao diện được "liên tục". Tức là khi có một sự thay đổi về mặt dữ liệu trong nguồn dữ liệu, sự thay đổi đó sẽ lập tức được hiển thị trên giao diện.
Giả sử như bạn có 5 FoodItem, với 5 tên khác nhau. Bạn muốn thay đổi tên của item thứ 2, bạn chỉ cần truy xuất tới item 2 và thay đổi giá trị của thuộc tính foodName, trên giao diện sẽ tự động thay đổi theo mà không cần thêm một dòng code nào cả
Okie, khai báo thuộc tính nào


Bạn phải bắt buộc khai báo thêm 1 event và một Method trong class của mình sau khi khai báo Interface

 public event PropertyChangedEventHandler PropertyChanged;  
     protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)  
     {  
       PropertyChangedEventHandler handler = PropertyChanged;  
       if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));  
     }  

Nếu bạn có ReShaper, thì mọi việc đơn giản hơn nhiều


Tiếp tục chọn Yes nhé


Và bạn sẽ thấy kết quả


Lưu ý là ReSharper sẽ thêm một file vào Property của Project bạn đang viết


File Dropbox cho bạn nào không có ReSharper: https://db.tt/ycsvjt1S

Rồi, bây giờ ta sẽ tạo các Public Property
Một lần nữa, ReSharper sẽ giúp ích chúng ta.
Đặt con trỏ vào dưới các thuộc tính Private, chọn ReShaper > Edit > Generate Code…


Chọn Property cho hộp thoại hiện ra


Check cả 3 thuộc tính, check luôn tùy chọn "Notify on Property Changes"


Thế là bạn có 3 thuộc tính đúng chuẩn như sau


2.3 Nguồn dữ liệu

Bạn đã có 1 kiểu dữ liệu, bây giờ bạn sẽ cần 1 nguồn dữ liệu
Tạo một Folder mới tên Data


Tạo một class mới tên StaticData trong Folder đó


Khai báo một biến static ObservableCollection


Khi có ReSharper, nó sẽ tự động thêm các Namespace cần thiết cho bạn. Ở đây, class FoodItem thuộc namespace TestAd.Model
Kết quả là bạn có như sau:


2.4 Nạp dữ liệu

Bây giờ, ta sẽ nạp dữ liệu vào ObservableCollection này
Mở file code behind của page có chứa listbox mà bạn đã tạo trong phần 1
Khai báo như sau, bạn sẽ thấy kiểu khai báo này quen thuộc trong bài: [Windows Phone] Where to put LoadData method



Bước 1: kiểm tra dữ liệu đã tồn tại
Đặc trưng cơ bản của cách khai báo LoadData như thế này là khi ta navigate tới trang này, hoặc có sự thay đổi về elements trên giao diện, event OnLoaded sẽ được gọi lại.
Vì vậy, ta chỉnh sửa event OnLoaded để ngăn ngừa việc load lại dữ liệu như sau:

 private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)  
     {  
       if (StaticData.FoodItemCollection.Count == 0)  
       {  
         LoadData();  
       }  
     }  

Thêm một số code như sau vào hàm LoadData

CODE
 private void LoadData()  
     {  
       for (int i = 0; i < 5; i++)  
       {  
         FoodItem foodItem = new FoodItem();  
         foodItem.Id = i;  
         foodItem.FoodName = "Food Name is " + i;  
         foodItem.ImageLink = "FoodItem_" + i + "_imageLink";  
         StaticData.FoodItemCollection.Add(foodItem);  
       }  
     }  


Mục tiêu của đoạn code trên là add 5 item giả vào FoodItemCollection.

2.5 Binding

Vậy ta đã có dữ liệu, có nguồn dữ liệu, có luôn listbox, bây giờ ta sẽ tiến hành binding dữ liệu này vào listbox
Việc này được thực hiện bởi 1 dòng code duy nhất.
Đặt tên cho listbox của bạn:


Sửa event OnLoaded lại như sau:

CODE
 private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)  
     {  
       if (StaticData.FoodItemCollection.Count == 0)  
       {  
         LoadData();  
         FoodListBox.ItemsSource = StaticData.FoodItemCollection;  
       }  
     }  



Sau đó, bấm chạy thử trên Emulator hay trên Device tùy thích


Và đây chính là thành quả của các bạn


2.6 DataTemplate

Vậy là dữ liệu đã được hiển thị trên giao diện, nhưng không theo cách bạn mong muốn
Chính vì thế, ta sẽ tạo một DataTemplate cho Listbox, mục đích là để "định nghĩa" cách hiển thị dữ liệu
Vào code XAML của bạn, bấm chọn Document Outline


Document Outline là nơi thể hiện toàn bộ mọi thứ có trên giao diện của bạn dưới dạng cây
Bấm chuột phải vào ListBox của bạn và chọn




Đặt tên cho DataTemplate của bạn rồi nhấn OK


Nếu bạn chọn Define in Application, DataTemplate này có thể được dùng ở mọi page trong project của bạn mà không cần phải khai báo lại
Trong lúc thiết kế, bạn có thể thấy thiết kế của mình được hiển thị trực quan


Nhấn chạy một lần nữa, và mọi thứ sẽ đúng như ý bạn


  1. Event Handling

Vậy là bạn đã có 1 listbox, bây giờ ta sẽ áp dụng một số sự kiện cho nó để thông báo cho người dùng biết họ đã chọn Listbox nào
Trong Property của FoodListBox, chọn nút Event


Double Click vào event "Selection Changed" để khai báo event
Thêm đoạn code sau vào event mới được tạo

CODE
 if (FoodListBox.SelectedIndex != -1)  
       {  
         FoodItem foodItem = FoodListBox.SelectedItem as FoodItem;  
         MessageBox.Show(foodItem.FoodName);  
       }  

Chạy thử và chọn một item bất kỳ


Thật tuyệt vời phải không
Vậy là hết rồi, hẹn gặp lại các bạn ở episode tiếp theo của Series Absolute Beginner nhé

Nhận xét