Xây dựng và sử dụng UserControl trong WPF – Part 2
Trong phần trước, tôi đã trình bày về phần core của UserControl CarRacer. Phần này, tôi sẽ tiếp tục trình bày cách implement các hiệu ứng chuyển động của xe.
Đầu tiên tôi sẽ cài đặt hiệu ứng chuyển động của bánh xe. Ở đây tôi muốn giảm bớt số lượng code trong file code behind nên tôi sẽ cài đặt animation viết bằng mã XAML:
1
<span style="color:blue;"><</span><span style="color:#a31515;">UserControl.Resources</span><span style="color:blue;">> <</span><span style="color:#a31515;">Storyboard </span><span style="color:red;">x</span><span style="color:blue;">:</span><span style="color:red;">Key</span><span style="color:blue;">="WheelAnimation" </span><span style="color:red;">RepeatBehavior</span><span style="color:blue;">="Forever"> <</span><span style="color:#a31515;">DoubleAnimationUsingKeyFrames </span><span style="color:red;">Storyboard.TargetProperty</span><span style="color:blue;">="RenderTransform.Angle" </span><span style="color:red;">Storyboard.TargetName</span><span style="color:blue;">="Banh_Xe_2"> <</span><span style="color:#a31515;">EasingDoubleKeyFrame </span><span style="color:red;">Value</span><span style="color:blue;">="360"/> </</span><span style="color:#a31515;">DoubleAnimationUsingKeyFrames</span><span style="color:blue;">> <</span><span style="color:#a31515;">DoubleAnimationUsingKeyFrames </span><span style="color:red;">Storyboard.TargetProperty</span><span style="color:blue;">="RenderTransform.Angle" </span><span style="color:red;">Storyboard.TargetName</span><span style="color:blue;">="Banh_Xe_1"> <</span><span style="color:#a31515;">EasingDoubleKeyFrame </span><span style="color:red;">Value</span><span style="color:blue;">="360"/> </</span><span style="color:#a31515;">DoubleAnimationUsingKeyFrames</span><span style="color:blue;">> </</span><span style="color:#a31515;">Storyboard</span><span style="color:blue;">> </</span><span style="color:#a31515;">UserControl.Resources</span><span style="color:blue;">> </span>
Chúng ta khai báo một đối tượng kiểu Storyboard trong phần Resource của UserControl và có x:Key=”WheelAnimation”. Property RepeatBehavior được set thành Forever để đảm bảo bánh xe luôn luôn quay nếu xe vẫn còn đang chạy. Storyboard này có 2 child element kiểu DoubleAnimationUsingKeyFrames, mỗi element chính là thể hiện sự chuyển động quay tròn của mỗi bánh xe với TargetProperty là giá trị Angle của RotateTransform.
Tiếp theo, ta cài đặt hiệu ứng khi xe di chuyển trong phần code behind. Phương thức Run() sẽ thực hiện nhiệm vụ làm cho xe chạy, kết thúc chuyển động của bánh xe khi xe chạm đích và raise FinishedEvent. Nội dung của phương thức này như sau:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<span style="color:blue;">public void </span>Run()
{
<span style="color:green;">// calculate the time using formular t = s/v </span><span style="color:blue;">double </span>duration = Length / Speed;
<span style="color:green;">// Get the storyboard which handles the animation of the wheels when the car runs. </span><span style="color:#2b91af;">Storyboard </span>wheelAnimation = <span style="color:blue;">this</span>.Resources[<span style="color:#a31515;">"WheelAnimation"</span>] <span style="color:blue;">as </span><span style="color:#2b91af;">Storyboard</span>;
wheelAnimation.Duration = <span style="color:#2b91af;">TimeSpan</span>.FromSeconds(duration/2);
<span style="color:#2b91af;">Storyboard </span>carAnimation = <span style="color:blue;">new </span><span style="color:#2b91af;">Storyboard</span>();
<span style="color:#2b91af;">DoubleAnimation </span>animation = <span style="color:blue;">new </span><span style="color:#2b91af;">DoubleAnimation</span>();
animation.To = Length;
animation.Duration = <span style="color:#2b91af;">TimeSpan</span>.FromSeconds(duration);
<span style="color:#2b91af;">Storyboard</span>.SetTarget(animation, <span style="color:blue;">this</span>);
<span style="color:#2b91af;">Storyboard</span>.SetTargetProperty(animation, <span style="color:blue;">new </span><span style="color:#2b91af;">PropertyPath</span>(<span style="color:#a31515;">"(Canvas.Left)"</span>));
carAnimation.Children.Add(animation);
<span style="color:green;">// When the animation completed, it will stop the wheelAnimation and raise the FinishedEvent </span>carAnimation.Completed += <span style="color:blue;">delegate </span>{
wheelAnimation.Stop();
<span style="color:#2b91af;">RoutedEventArgs </span>re = <span style="color:blue;">new </span><span style="color:#2b91af;">RoutedEventArgs</span>(FinishedEvent);
<span style="color:blue;">this</span>.RaiseEvent(re);
};
carAnimation.Begin();
wheelAnimation.Begin();
}
Như vậy, toàn bộ hoạt động của CarRacer control đã được cài đặt xong. Bây giờ chúng ta chuyển sang project CarRacerDemo để chạy thử control này. Trong file MainWindow.xaml, tôi đã thay đổi một số chi tiết như giá trị Speed của xe xanh để tạo ra sự khác biệt về chuyển động giữa 2 xe. Bên cạnh đó là một phương thức sẽ được thực thi mỗi khi event Finished được gọi (chỉ đơn giản là show messagebox).
Một Button cũng được thêm vào để gọi phương thức Run() của mỗi đối tượng CarRacer. Nội dung của file MainWindow.xaml như sau:
1
<span style="color:blue;"><</span><span style="color:#a31515;">Window </span><span style="color:red;">x</span><span style="color:blue;">:</span><span style="color:red;">Class</span><span style="color:blue;">="CarRacerDemo.MainWindow" </span><span style="color:red;">xmlns</span><span style="color:blue;">="http://schemas.microsoft.com/winfx/2006/xaml/presentation" </span><span style="color:red;">xmlns</span><span style="color:blue;">:</span><span style="color:red;">x</span><span style="color:blue;">="http://schemas.microsoft.com/winfx/2006/xaml" </span><span style="color:red;">xmlns</span><span style="color:blue;">:</span><span style="color:red;">car</span><span style="color:blue;">="clr-namespace:CarRacer;assembly=CarRacer" </span><span style="color:red;">Title</span><span style="color:blue;">="MainWindow" </span><span style="color:red;">Height</span><span style="color:blue;">="250" </span><span style="color:red;">Width</span><span style="color:blue;">="525"> <</span><span style="color:#a31515;">Canvas</span><span style="color:blue;">> <</span><span style="color:#a31515;">car</span><span style="color:blue;">:</span><span style="color:#a31515;">CarRacer </span><span style="color:red;">Width</span><span style="color:blue;">="100" </span><span style="color:red;">Height</span><span style="color:blue;">="55" </span><span style="color:red;">Speed</span><span style="color:blue;">="150" </span><span style="color:red;">Canvas.Top</span><span style="color:blue;">="10" </span><span style="color:red;">Canvas.Left</span><span style="color:blue;">="0" </span><span style="color:red;">Source</span><span style="color:blue;">="pack://application:,,,/CarRacerDemo;component/Than_xe.png" </span><span style="color:red;">x</span><span style="color:blue;">:</span><span style="color:red;">Name</span><span style="color:blue;">="xe_xanh" </span><span style="color:red;">Margin</span><span style="color:blue;">="0 10" </span><span style="color:red;">Finished</span><span style="color:blue;">="car_Finished"/> <</span><span style="color:#a31515;">car</span><span style="color:blue;">:</span><span style="color:#a31515;">CarRacer </span><span style="color:red;">Grid.Row</span><span style="color:blue;">="1" </span><span style="color:red;">Width</span><span style="color:blue;">="100" </span><span style="color:red;">Height</span><span style="color:blue;">="55" </span><span style="color:red;">Canvas.Top</span><span style="color:blue;">="100" </span><span style="color:red;">Canvas.Left</span><span style="color:blue;">="0" </span><span style="color:red;">Source</span><span style="color:blue;">="pack://application:,,,/CarRacerDemo;component/Xe_Do.png" </span><span style="color:red;">x</span><span style="color:blue;">:</span><span style="color:red;">Name</span><span style="color:blue;">="xe_do" </span><span style="color:red;">Margin</span><span style="color:blue;">="0 10" </span><span style="color:red;">Finished</span><span style="color:blue;">="car_Finished" /> <</span><span style="color:#a31515;">Button </span><span style="color:red;">Content</span><span style="color:blue;">="Run The Car" </span><span style="color:red;">Grid.Row</span><span style="color:blue;">="2" </span><span style="color:red;">HorizontalAlignment</span><span style="color:blue;">="Center" </span><span style="color:red;">VerticalAlignment</span><span style="color:blue;">="Top" </span><span style="color:red;">Padding</span><span style="color:blue;">="10" </span><span style="color:red;">Click</span><span style="color:blue;">="Button_Click" </span><span style="color:red;">Canvas.Top</span><span style="color:blue;">="170" </span><span style="color:red;">Canvas.Left</span><span style="color:blue;">="210" /> </</span><span style="color:#a31515;">Canvas</span><span style="color:blue;">> </</span><span style="color:#a31515;">Window</span><span style="color:blue;">> </span>
File MainWindow.xaml.cs thêm vào 2 phương thức, 1 phương thức thực thi khi sự kiện Button.Click được gọi, phương thức còn lại là khi event CarRacer.Finished được gọi. Hai phương thức này được khai báo như sau:
1
2
3
4
5
6
7
8
9
10
<span style="color:blue;">private void </span>Button_Click(<span style="color:blue;">object </span>sender, <span style="color:#2b91af;">RoutedEventArgs </span>e)
{
xe_do.Run();
xe_xanh.Run();
}
<span style="color:blue;">private void </span>car_Finished(<span style="color:blue;">object </span>sender, <span style="color:#2b91af;">RoutedEventArgs </span>e)
{
<span style="color:#2b91af;">MessageBox</span>.Show((sender <span style="color:blue;">as </span>CarRacer.<span style="color:#2b91af;">CarRacer</span>).Name + <span style="color:#a31515;">" finished!"</span>);
}
Bây giờ bạn có thể chạy thử chương trình và xem thử kết quả. Bài viết này mục đích chính là để giới thiệu cách define UserControl, DependencyProperty và RoutedEvent, đồng thời cũng hướng dẫn cách sử dụng lại các UserControl trong các project khác.
Download source: http://www.mediafire.com/?6url3arsrxgaqzg
Comments powered by Disqus.