Blog chia sẽ kinh nghiệm lập trình và Technical VN. Nơi mà các bạn có thể học tập và tham khảo về những công nghệ mới nhất hiện nay về .NET

Chủ Nhật, 8 tháng 2, 2015


Lâu nay, Need for Speed là một tựa game mà tôi vẫn hay chơi cho thõa đam mê về  tốc độ. Tựa game này có một bộ Controllers vô cùng hoành tráng nhưng đối với một anh sinh viên mê đua xe thì quá đắt vì thế tôi cứ phải chơi với bàn phím Laptop. Nay có thêm chiếc SmartPhone tôi lại đua xe và cứ thế xoay xoay điện thoại - có một vấn đề vô cùng ức chế là tôi bị cận và màng hình ĐT thì quá bé cho một tựa game 3D với nhiều cảnh quay hoành tá tràng.  Để tận dụng ưu điểm của SmartPhone và Laptop, trong bài viết này tôi sẽ giới thiệu đến các bạn một trong số nhiều ứng dụng rất hay mà tôi biết để có thể tận dụng cảm biến góc nghiêm trên phone và màng hình lớn của Laptop.





Nhu cầu:




  • Chơi game 3D khủng trên Laptop(PC)

  • Tay cầm chơi game(gamepad) không dây với cảm biến góc nghiên và cảm biến gia tốc


Yêu cầu:




  • Laptop/PC phải cài được game "Dò mìn" hoặc "Pikachu" của Microsoft

  • Laptop phải có Bluetooth hoặc Wifi còn hoạt động tốt

  • Điện thoại phải là SmartPhone và Bluetooth/Wifi còn hoạt động tốt

  • Chức năng cảm ứng và các cảm biến cần thiết trên Phone không bị liệt



Mô hình tương tác:



Chúng ta sẽ có một App trên SmartPhone và một app trên PC đóng vai trò là Server. Khi chúng ta touch trên SPhone lập tức app trên PC sẽ nhận được tín hiệu và chuyển thành mã phím tương ứng gửi tiếp cho Game, vậy SPhone chúng ta sẽ thay thế bàn phím, để chơi đc Game chúng ta cần đồng bộ các Button trên SPhone với các Phím đã cấu hình trong game.


Tiến hành cài đặt hai App trên SPhone và PC theo đường dẫn sau




Các bước cấu hình như sau:


Step 1: Kết nối wifi cho hai thiết bị vào cùng một mạng wifi và nhớ địa chỉ IP đang truy cập wifi trên PC sau đó chuyển đến Step 3


Step 2: Nếu không có một trạm wifi nào gần bạn hoặc không truy cập hai thiết bị trên vào cùng mạng wifi xin làm theo cách sau



Mở tính năng điểm truy cập trên SPhone lên và Connect PC vào mạng này, nếu kết nối thành công xin xem kỹ hình dưới đây(samsung J) - chúng ta sẽ thấy tên PC và địa chỉ IP, đây chính là địa chỉ IP của server(nhớ nó)



Step 3: Chạy appServer lên và cấu hình như sau


1) Vào tab Games, nhấn [(+)] để thêm games mà bạn muốn chạy cùng SPhone



2) Nhấn Browse để duyệt đến tập tin thực thi của Game, sau đó tiến hành cấu hình cho các Button bằng cách Click chuột vào Button cần sửa và nhấn phím mà bạn muốn Button này sẽ đại diện(nếu không hình dung được các Button này trên SPhone thế nào bạn có thể cấu hình bước này sau. Cuối cùng đặt tên cho gameSeting và [OK]



3) Vào tab Settings, chọn địa chỉ IP của server tại combobox "Listen to", các cài đặt khác nên để mặc định - nhớ chọn đúng IP ở Step 1/2;  sau đó chọn [update]



Step 4: Chạy appClient lên và chọn Wifi sau đó nhập chính xác IP của server và port(12400).



Step 5: Khi kết nối thành công, chúng ta có màng hình như sau, nhớ quay lại bước 3-2 để cấu hình các Button



=> Chú ý: Mặc định chúng ta có 4 Button điều hướng, chúng ta có thể không sử dụng 4 Button này mà sử dụng cảm biến góc nghiên, để thay đổi chế độ này hãy chọn vào 2 Button ở gần biểu tượng wifi để mở chức năng dùng cảm biến, mở cả hai chức năng để có thể nghiêng điện thoại theo 4 chiều. Khi nghiêng điện thoại nhớ nhấn giữ vòng tròn lớn bênh trái.



Step 6: Để chơi game, chúng ta Touch vào biểu tượng 9 ô vuông nhỏ, list các game chúng ta đẽ thêm ở bước 3-2 hiện ra, chọn game muốn chơi và thưởng thức




Và giờ chúng ta đã có cái này



Chúc các bạn vui vẻ!


Phạm Tuân


Design Pattern là một kỹ thuật trong lập trình hướng đối tượng, nó khá quan trọng và mọi lập trình viên muốn giỏi đều phải biết. Được sử dụng thường xuyên trong các ngôn ngữ OOP. Nó sẽ cung cấp cho bạn các "mẫu thiết kế", giải pháp để giải quyết các vấn đề chung, thường gặp trong lập trình. Các vấn đề mà bạn gặp phải có thể bạn sẽ tự nghĩ ra cách giải quyết nhưng có thể nó chưa phải là tối ưu. Design Pattern giúp bạn giải quyết vấn đề một cách tối ưu nhất, cung cấp cho bạn các giải pháp trong lập trình OOP.




Design Pattern có 23 mẫu cơ bản(GoF) và hình dưới là mối quang hệ giữa chúng


Trong Design Pattern có 3 nhóm bao gồm:


Creational Pattern (nhóm khởi tạo) gồm: Abstract Factory, Factory Method, Singleton, Builder, Prototype. Nó sẽ giúp bạn trong việt khởi tạo đối tượng, như bạn biết để khởi tạo bạn phải sử dụng từ khóa new, nhóm Creational Pattern sẽ sử dụng một số thủ thuật để khởi tạo đối tượng mà bạn sẽ không nhìn thấy từ khóa này.
Structural Pattern (nhóm cấu trúc) gồm: Adapter, Bridge, Composite, Decorator, Facade, Proxy và Flyweight.. Nó dùng để thiết lập, định nghĩa quan hệ giữa các đối tượng.
Behavioral Pattern gồm: Interpreter, Template Method, Chain of Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy và Visitor. Nhóm này dùng trong thực hiện các hành vi của đối tượng.


Design Pattern giúp bạn tái sử dụng mã lệnh và dễ dàng mở rộng. Để chuẩn bị học Design Pattern bạn cần phải nắm chắc các khái niệm sau:




  • Bốn đặc tính của OOP: Thừa kế, Đa hình, Trừu tượng, Bao đóng.

  • Khái niệm interface abstract. Cái này cực kỳ quan trọng, để hiểu và áp dụng 2 khái niệm này có thể sẽ mất một thời gian, nhưng khi bạn nắm chắc nó bạn sẽ thấy nó thực sự cần thiết.

  • Bỏ tư duy theo lối cấu trúc, nâng tư duy hoàn toàn OOP.


Tại sao sử dụng Design Pattern?


Design pattern cung cấp giải pháp ở dạng tổng quát, giúp tăng tốc độ phát triển phần mềm bằng cách đưa ra các mô hình test, mô hình phát triển đã qua kiểm nghiệm. Thiết kế phần mềm hiệu quả đòi hỏi phải cân nhắc các vấn đề sẽ nảy sinh trong quá trình hiện thực hóa (implementation). Dùng lại các design pattern giúp tránh được các vấn đề tiềm ẩn có thể gây ra những lỗi lớn, dễ dàng nâng cấp, bảo trì về sau.
Một lợi thế lớn để sử dụng một mẫu thiết kế là lập trình viên khác sẽ có thể dễ dàng nhận ra nó (đặc biệt là nếu bạn sử dụng quy ước đặt tên tốt).


Khi nào nên sử dụng Design pattern?


Đó là khi bạn muốn giữ cho chương trình của mình thực sự đơn giản. Việc sử dụng các design pattern sẽ giúp chúng ta giảm được thời gian và công sức suy nghĩ ra các cách giải quyết cho những vấn đề đã có lời giải. Bạn có thể đọc qua cuốn “Head First Design Patterns” để có cái nhìn tổng quát hơn về design pattern.
Hệ thống các mẫu design pattern chuẩn hiện có 23 mẫu được định nghĩa trong cuốn "Design patterns Elements of Reusable Object Oriented Software" mà khởi đầu là cuốn "Gang of Four (GoF)". Các tác giả của cuốn sách là Erich Gamma, Richard Helm, Ralph Johnson và John Vlissides, hay còn được biết đến với các tên "Gang of Four" hay đơn giản là "GoF". Hệ thống các mẫu này có thể nói là đủ và tối ưu cho việc giải quyết hết các vấn đề của bài toán phân tích thiết kế và xây dựng phần mềm trong thời điểm hiện tại. Hệ thống các mẫu design pattern được chia thành 3 nhóm: nhóm Creational (5 mẫu), nhóm Structural (7 mẫu) và nhóm Behavioral (11 mẫu).








































































































































STTTênMục đích
Nhóm Creational (nhóm kiến tạo)
1Abstract FactoryCung cấp một interface cho việc tạo lập các đối tượng (có liên hệ với nhau) mà không cần qui định lớp khi hay xác định lớp cụ thể (concrete) tạo mỗi đối tượngTần suất sử dụng: cao
2BuilderTách rời việc xây dựng (construction) một đối tượng phức tạp khỏi biểu diễn của nó sao cho cùng một tiến trình xây dựng có thể tạo được các biểu diễn khác nhau.Tần suất sử dụng: trung bình thấp
3Factory MethodĐịnh nghĩa Interface để sinh ra đối tượng nhưng để cho lớp con quyết định lớp nào được dùng để sinh ra đối tượng Factory method cho phép một lớp chuyển quá trình khởi tạo đối tượng cho lớp con.Tần suất sử dụng: cao
4PrototypeQui định loại của các đối tượng cần tạo bằng cách dùng một đối tượng mẫu, tạo mới nhờ vào sao chép đối tượng mẫu này.Tần suất sử dụng: trung bình
5SingletonĐảm bảo 1 class chỉ có 1 instance và cung cấp 1 điểm truy xuất toàn cục đến nó.Tần suất sử dụng: cao trung bình
Nhóm Structural (nhóm cấu trúc)
6AdapterDo vấn đề tương thích, thay đổi interface của một lớp thành một interface khác phù hợp với yêu cầu người sử dụng lớp.Tần suất sử dụng: cao trung bình
7BridgeTách rời ngữ nghĩa của một vấn đề khỏi việc cài đặt ; mục đích để cả hai bộ phận (ngữ nghĩa và cài đặt) có thể thay đổi độc lập nhau.Tần suất sử dụng: trung bình
8CompositeTổ chức các đối tượng theo cấu trúc phân cấp dạng cây; Tất cả các đối tượng trong cấu trúc được thao tác theo một cách thuần nhất như nhau.Tạo quan hệ thứ bậc bao gộp giữa các đối tượng. Client có thể xem đối tượng bao gộp và bị bao gộp như nhau -> khả năng tổng quát hoá trong code của client -> dễ phát triển, nâng cấp, bảo trì.Tần suất sử dụng: cao trung bình
9DecoratorGán thêm trách nhiệm cho đối tượng (mở rộng chức năng) vào lúc chạy (dynamically).Tần suất sử dụng: trung bình
10FacadeCung cấp một interface thuần nhất cho một tập hợp các interface trong một “hệ thống con” (subsystem). Nó định nghĩa 1 interface cao hơn các interface có sẵn để làm cho hệ thống con dễ sử dụng hơn.Tần suất sử dụng: cao
11FlyweightSử dụng việc chia sẻ để thao tác hiệu quả trên một số lượng lớn đối tượng “cở nhỏ” (chẳng hạn paragraph, dòng, cột, ký tự…).Tần suất sử dụng: thấp
12ProxyCung cấp đối tượng đại diện cho một đối tượng khác để hỗ trợ hoặc kiểm soát quá trình truy xuất đối tượng đó. Đối tượng thay thế gọi là proxy.Tần suất sử dụng: cao trung bình
Nhóm Behavioral (nhóm tương tác)
13Chain of ResponsibilityKhắc phục việc ghép cặp giữa bộ gởi và bộ nhận thông điệp; Các đối tượng nhận thông điệp được kết nối thành một chuỗi và thông điệp được chuyển dọc theo chuỗi nầy đến khi gặp được đối tượng xử lý nó.Tránh việc gắn kết cứng giữa phần tử gởi request với phần tử nhận và xử lý request bằng cách cho phép hơn 1 đối tượng có có cơ hội xử lý request . Liên kết các đối tượng nhận request thành 1 dây chuyền rồi “pass” request xuyên qua từng đối tượng xử lý đến khi gặp đối tượng xử lý cụ thể.Tần suất sử dụng: trung bình thấp
14CommandMỗi yêu cầu (thực hiện một thao tác nào đó) được bao bọc thành một đối tượng. Các yêu cầu sẽ được lưu trữ và gởi đi như các đối tượng.Đóng gói request vào trong một Object , nhờ đó có thể nthông số hoá chương trình nhận request và thực hiện các thao tác trên request: sắp xếp, log, undo…Tần suất sử dụng: cao trung bình
15InterpreterHỗ trợ việc định nghĩa biểu diễn văn phạm và bộ thông dịch cho một ngôn ngữ.Tần suất sử dụng: thấp
16IteratorTruy xuất các phần tử của đối tượng dạng tập hợp tuần tự (list, array, …) mà không phụ thuộc vào biểu diễn bên trong của các phần tử.Tần suất sử dụng: cao
17MediatorĐịnh nghĩa một đối tượng để bao bọc việc giao tiếp giữa một số đối tượng với nhau.Tần suất sử dụng: trung bình thấp
18MementoHiệu chỉnh và trả lại như cũ trạng thái bên trong của đối tượng mà vẫn không vi phạm việc bao bọc dữ liệu.Tần suất sử dụng: thấp
19ObserverĐịnh nghĩa sự phụ thuộc một-nhiều giữa các đối tượng sao cho khi một đối tượng thay đổi trạng thái thì tất cả các đối tượng phụ thuộc nó cũng thay đổi theo.Tần suất sử dụng: cao
20StateCho phép một đối tượng thay đổi hành vi khi trạng thái bên trong của nó thay đổi , ta có cảm giác như class của đối tượng bị thay đổi.Tần suất sử dụng: trung bình
21StrategyBao bọc một họ các thuật toán bằng các lớp đối tượng để thuật toán có thể thay đổi độc lập đối với chương trình sử dụng thuật toán.Cung cấp một họ giải thuật cho phép client chọn lựa linh động một giải thuật cụ thể khi sử dụng.Tần suất sử dụng: cao trung bình
22Template methodĐịnh nghĩa phần khung của một thuật toán, tức là một thuật toán tổng quát gọi đến một số phương thức chưa được cài đặt trong lớp cơ sở; việc cài đặt các phương thức được ủy nhiệm cho các lớp kế thừa.Tần suất sử dụng: trung bình
23VisitorCho phép định nghĩa thêm phép toán mới tác động lên các phần tử của một cấu trúc đối tượng mà không cần thay đổi các lớp định nghĩa cấu trúc đó.Tần suất sử dụng: thấp

Bạn có thể học Design pattern ở đâu




  • Cuốn sách nổi tiếng nhất và là khởi đầu của Design pattern là "Gang of Four (GoF)"

  • Trang mạng uy tín để bạn có thể học thêm ngoài 23 mẫu cơ bản là "Sourcemaking.com" có code mẫu

  • Kênh youtube có "Derek Banas", "Mohammad Alqerm" và khá nhiều kênh khác


Đây là source một số pattern thông dụng theo kinh nghiệm của tôi.


Chúc các bạn thành công!


Phạm Tuân


Trích theo mr.datnh



Chủ Nhật, 1 tháng 2, 2015


Sau Dependency property, chúng ta sẽ tiếp tục tìm hiểu về Attached property - một loại property không thuộc đối tượng trực tiếp sử dụng nó(khác Dependency property). Dễ hiểu hơn có nghĩa là property này được định nghĩa ở một class/object khác và được dùng như một property của class/object này(na ná cách dùng của Extension methods), bởi thế mới gọi là Attached.




Bạn có thể thấy một số Attached property khi sử dụng các panel: Dock, Grid, Canvas ... Trong ví dụ dưới đây, chúng ta set giá trị DockPanel.Dock cho TextBox là "Top", xong property Dock lại không phải là một property thuộc TextBox - đó là một Attached property được định nghĩa ở DockPanel, attached property này dùng cho tất cả các control đang được chứa bởi DockPanel.




[code language="xml"]
<TextBox DockPanel.Dock=”Top”>Attached property</TextBox>
[/code]

Để tạo một attached property chúng ta phải tuân theo cấu trúc này( hãy liên tưởng đến bài Dependency property trước để có sự so sánh về cách đăng ký một attached property - không khéo là nhầm lẫn đấy)




[code language="csharp"]
public class RotationManager
{
public static propertyType Get[+ propertyName](DependencyObject obj)
{
//TODO: need to implement now
return (propertyType)obj.GetValue([propertyName+]Property);
}
public static void Set[+ propertyName](DependencyObject obj, propertyType value)
{
//TODO: need to implement now
obj.SetValue([propertyName+]Property, value);
}

public static readonly DependencyProperty [propertyName+]Property =
DependencyProperty.RegisterAttached("propertyName",
typeof(propertyType), typeof(ownerType),
new [defaultMetadata](0.5, [propertyChangedCallback]));

private static void propertyChangedCallback(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
//TODO: need to implement now
}
}
[/code]

Diễn gải:




  • propertyName: Là tên của property bạn muốn tạo ví dụ "Dock"

  • propertyType: Là Type mà attached property này nhận

  • ownerType: là Type của đối tượng chịu trách nhiệm(Owner) property này, ví dụ DockPanel

  • propertyChangedCallback: là hàm sẽ được gọi khi Value của attached property bị thay đổi

  • defaultMetadata: là một object thuộc PropertyMetadata - chỉ loại các đối tượng sẽ được thừa hưởng property này

    • FrameworkPropertyMetadata: tất cả các element trong XAML

    • UIPropertyMetadata: là các UI element/Control trong XAML




Ví dụ trực quan: Tôi có một Path, tôi xoay nó với góc 50 độ và được như hình sau

XAML thế này




[code language="xml"]
<Grid Background="White" Margin="25">
<Path Stretch="Uniform" Fill="#FF08578B" Data="F1 M 28.4583,20.8296C 28.9254,20.4138 29.2514,19.768 29.4364,18.8921C 29.6214,18.0162 29.4554,17.0984 28.9384,16.1389C 29.3694,14.16 29.0234,12.7686 27.9003,11.9646C 26.7772,11.1607 25.4592,10.7729 23.946,10.8015L 23.274,10.8015C 23.614,10.1266 23.882,9.40756 24.0781,8.64438C 24.2741,7.8812 24.3741,7.20871 24.3781,6.62686C 24.3166,4.37555 23.8036,2.70673 22.839,1.62039C 21.8744,0.534058 20.8272,-0.006073 19.6976,0C 17.6181,0.0614014 16.274,1.37863 15.6653,3.95166C 15.6406,4.27734 15.1563,5.48642 14.2124,7.57889C 13.2686,9.67136 11.8711,11.4226 10.02,12.8326L 10.02,11.6045C 9.94067,10.959 9.57507,10.5968 8.92316,10.5181L 1.0975,10.5181C 0.445374,10.5968 0.0795288,10.959 0,11.6045L 0,30.0051C 0.0795288,30.7017 0.445374,31.086 1.0975,31.1581L 8.92316,31.1581C 9.57507,31.086 9.94067,30.7017 10.02,30.0051L 10.02,27.7953C 10.7491,28.3628 12.6754,28.989 15.7988,29.6737C 18.9222,30.3584 21.8093,30.4828 24.46,30.0469C 27.1107,29.6109 28.0914,27.9957 27.4023,25.2011C 28.0253,24.7488 28.4593,24.1283 28.7043,23.3396C 28.9493,22.551 28.8674,21.7143 28.4583,20.8296 Z M 24.2341,20.7815C 25.4911,21.0257 26.0372,21.5341 25.8722,22.3068C 25.7072,23.0794 24.7771,23.5158 23.082,23.6158C 22.812,23.6399 22.68,23.748 22.686,23.9401C 22.692,24.1323 22.872,24.2644 23.226,24.3365C 24.8361,24.7918 25.4081,25.4303 24.9421,26.252C 24.4761,27.0737 23.392,27.5081 21.6899,27.5551C 20.587,27.5541 19.0097,27.388 16.9579,27.0567C 14.9062,26.7254 12.5936,25.9468 10.02,24.7208L 10.02,16.0445C 11.9097,15.114 13.6807,13.4388 15.3332,11.0186C 16.9857,8.59857 17.9977,6.34018 18.3693,4.2435C 18.4157,3.81894 18.5482,3.46432 18.7666,3.17972C 18.985,2.89514 19.2953,2.74728 19.6976,2.73615C 20.1107,2.74524 20.5296,3.09171 20.9543,3.77557C 21.3792,4.45944 21.6083,5.42606 21.6419,6.67551C 21.5589,7.68878 21.227,8.72198 20.646,9.77512C 20.0651,10.8282 19.7331,11.6585 19.6501,12.2657C 19.6491,12.525 19.7697,12.765 20.0118,12.9858C 20.254,13.2066 20.6236,13.324 21.1207,13.3381L 23.946,13.3381C 25.3041,13.4708 26.0562,14.0019 26.2022,14.9312C 26.3482,15.8606 25.8042,16.3916 24.5701,16.5244C 24.3061,16.5867 24.1741,16.7006 24.1741,16.8661C 24.1741,17.0316 24.3061,17.1356 24.5701,17.1781C 25.8192,17.3445 26.4172,17.853 26.3642,18.7038C 26.3112,19.5545 25.6012,20.0389 24.2341,20.157C 23.9221,20.177 23.7661,20.2691 23.7661,20.4332C 23.7661,20.5974 23.9221,20.7135 24.2341,20.7815 Z "
RenderTransformOrigin="0.5,0.5">

<!-- Xoay -->
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="50"/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>
</Grid>
[/code]

Chú ý rằng tôi xoay Path trên nhờ đoạn XAML sau




[code language="xml"]
<Path Stretch="Uniform" Fill="#FF08578B" Data="............."
RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="50"/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path></pre>
<pre>[/code]

Nhưng tôi thấy nó quá dài - đến vài thẻ XAML cho một giá trị Angle="50", nếu tôi dùng phép xoay này nhiều lần trong một file XAML hoặc nhiều file XAML khác thì thật rối mắt, vậy nên tôi tạo ra một attached property thay thế đoạn XAML kia như sau




[code language="csharp"]
public class RotationManager
{
/// <summary>
/// Get giá trị của attached property
/// </summary>
/// <param name="obj">Đối tượng Dependency</param>
/// <returns>Giá trị của attached property</returns>
public static double GetAngle(DependencyObject obj)
{
return (double)obj.GetValue(AngleProperty);
}

/// <summary>
/// Set giá trị góc cho đối tượng
/// </summary>
/// <param name="obj">Đối tượng Dependency</param>
/// <param name="value">Giá trị do user input</param>
public static void SetAngle(DependencyObject obj, double value)
{
obj.SetValue(AngleProperty, value);
throw new NoNullAllowedException();
}

public static readonly DependencyProperty AngleProperty =
DependencyProperty.RegisterAttached("Angle",
typeof(double), typeof(RotationManager),
new UIPropertyMetadata(0.5, OnAngleChanged));

/// <summary>
/// CallBack khi value của property thay đổi
/// </summary>
/// <param name="obj">Đối tượng Dependency</param>
/// <param name="e"></param>
private static void OnAngleChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
var element = obj as UIElement;
if (element != null)
{
element.RenderTransformOrigin = new Point(.5, .5);
element.RenderTransform = new RotateTransform((double)e.NewValue);
}
}
}
[/code]

Và dùng đơn giản thế này, tôi tiến hành xoay góc 180 độ




[code language="xml"]
<Grid Background="White" Margin="25">
<Path Stretch="Uniform" Fill="#FF08578B" Data="Như củ" RenderTransformOrigin="0.5,0.5"
local:RotationManager.Angle="180"/>
</Grid>
[/code]

Hãy so sánh với đoạn code trước

[code language="xml"]
<!-- khi không dùng attached property -->
<Path Stretch="Uniform" Fill="#FF08578B" Data="............."
RenderTransformOrigin="0.5,0.5">
<Path.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="50"/>
<TranslateTransform/>
</TransformGroup>
</Path.RenderTransform>
</Path>

<!-- khi dùng attached property thì code chỉ thế này -->
<Path Stretch="Uniform" Fill="#FF08578B" Data="............."
RenderTransformOrigin="0.5,0.5"
local:RotationManager.Angle="180"/>
[/code]

Kết quả


Chúc mọi người thành công!
Phạm Tuân