Lời nói đầu

Lâu lắm rồi mới lại viết blog, nay hứng chí nên quyết định viết một bài cho vui, cơ mà cũng lười nên nội dung sẽ không cụ thể và chi tiết lắm😀.

Cái title của bài này hình như hơi bị chuối :v, nhưng mà thú thật là cũng không biết đặt cái title khác như thế nào… Thôi thì tí mọi người xem nội dung rồi sẽ biết😀.

WHY and WHAT?

Phần này để nói về lý do tại sao hôm nay lại viết có hứng viết cái bài này, và nó viết về cái gì.

Tại sao lại có hứng? Chả biết, mấy nay trong quá trình làm việc, trải nghiệm qua vài cái, customize được vài cái (iOS, WinPhone, blah blah), muốn viết bài share cho mọi người cùng sử dụng (chém gió thôi chứ thực ra mục đích là viết lấy le, share link lên FB để làm màu thôi, lol… j/k).

Bài này viết về cái gì? Nói chung thì đang làm một cái project Windows Phone nho nhỏ, cần sử dụng đến expander view. Nó trông như vầy:

pic1
Hình 1. Cái expander view mà tui đang làm

ExpanderView là một control trong Windows Phone toolkit, ai đọc đến khúc này chắc cũng biết rồi, khỏi giới thiệu😀. Như vậy là rõ mục đích rồi ha, ExpanderView được dùng để biểu diễn cấu trúc dữ liệu cây (1 cấp thôi, mà nhiều cấp cũng chả ai cấm :D). Điều kiện là khi CheckBox ở Header (Header là nguyên cái cục CheckBox và chữ Parent Group á) ở trạng thái IsChecked = True thì các CheckBox của Sub Group cũng phải check luôn (và ngược lại).

Ngồi làm DataTemplate đã đời ông địa rồi, run thử trên emulator, bấm tưng bừng vào cái CheckBox ở Header mà chẳng thấy thay đổi cái quái gì hết L. Vậy thì người nông rân phải làm sao?

Giải quyết

Đầu tiên là nghĩ tới việc subscribe event Clicked của cái CheckBox và đặt breakpoint thử xem thế, kết quả là… không có gì thay đổi, event không được gọi. Thế là thế quái nào -_-

Si nghĩ si nghĩ… Đoán chắc là do cái cái event Tap xử lý khi user touch lên cái header nó không có route (RoutedEvent) xuống bên dưới nữa nên cái CheckBox không raised Clicked event lên. OK, vậy thì chơi biện pháp mạnh. Giải pháp nghĩ ra lúc này là subscribe event Tap của cả cái Header, get position mà người dùng tap lên màn hình, kiểm tra xem vị trí đó có thuộc vị trí của cái CheckBox không, nếu có thì raise event, hay ít nhất cũng thay đổi value của cái property IsChecked. Làm một hồi… không get được position của cái CheckBox, lol =)))))

Haizz, giải pháp cuối cùng, đó là download source code của Windows Phone Toolkit về xem nó viết thế nào. Mở file Generic.xaml ra, find đến chỗ cái ExpanderView, thì ra nó được viết như này:

 pic2

Như vậy là cái Grid ExpanderPanel nó nằm trên cái Header rồi, kiểm tra trong file ExpanderView.cs thì thấy nó bắt sự kiện tap vào cái ExpanderPanel để expand và collapse items. Thế này thì có mà bắt sự kiện bằng niềm tin :v.

Rồi, nguyên nhân đã tìm thấy. Thế phải giải quyết làm sao? Chung quy lại thì cũng dễ, cơ mà lười viết nên sẽ túm tắt lại idea, ai quan tâm thì download solution về mở lên xem là hiểu😀.

1. Tạo ra cái ContentControl đặt ở bên trái cái Header, trong solution thì mình đặt tên nó là LeftHeaderButtonBase. Nói ButtonBase là để chỉ các loại control như Button, Hyperlink, RadioButton, CheckBox… nhưng thực chất thì nó là cái gì cũng được😀

2. Trong file ExpanderView.cs, khai báo 2 dependency property với tên là LeftHeaderButtonBase và LeftHeaderButtonBaseTemplate

3.  Thêm vào VisualStateGroup như sau:

pic4

4. Tạo 1 dependency property tên là ShowHeaderWithLeftButton kiểu bool trong file ExpanderView.cs, handle khi value changed, nếu true thì GoToState(“HeaderWithLeftButton”), ngược lại thì là GoToState(“NormalHeader”)

5. Tình hình là lúc nãy publish lên bị lỗi, mất bài viết, chỉ recovery được đến đây. Chỗ số 5 này có cái gì đó, viết rồi nhưng giờ bị mất nên không nhớ -_-

6. … không biết hết 5 cái trên còn cái nào nữa không😀.

7. Build project, xong add reference bên project windows phone về cái assembly mới build được.

Rồi xong, bây giờ edit lại mấy cái data template dùng cho ExpanderView:

pic5

Thêm vào vài dòng code xử lý logic để mấy cái CheckBox hoạt động theo đúng yêu cầu là OK. Tính làm cái ảnh gif animation mô tả kết quả cho sinh động nhưng mà thôi, lười quá😀.

KẾT BÀI

ĐÂY LÀ CÁI KẾT BÀI. CHẤM HẾT!!!

pic6

P.S: source code nó nằm ở http://sdrv.ms/1aydyW6. Văn phong viết bài của tớ nó là thế, không thích các thể loại nghiêm túc (mấy bài trước toàn nghiêm túc :v), vậy nên ai không thích thì… thôi vậy, I don’t care :)). Có thời gian sẽ viết thêm mấy bài nữa (nhưng chắc không đâu ^_^)