Tin tổng hợp

Bài 7: Xử lý sự kiện và lệnh trong WPF

  1. Xử lý sự kiện trong WPF

1.1.           Sự kiện

là một hành động được phát động bởi người dùng, bởi một thiết bị như đồng hồ đếm (timer) hay bàn phím, hoặc thậm chí là bởi hệ điều hành, tại những thời điểm phần lớn là không theo  chu trình nhất định. Mỗi khi một sự kiện xảy ra, thông thường dữ liệu liên quan đến sự kiện đó được thu thập và chuyển nó tới một đơn vị xử lý sự kiện (event handler) để xử lý tiếp. Cũng có khi, sự kiện bị bỏ qua hay chuyển tới nhiều hàm xử lý sự kiện một lúc nếu những hàm xử lý này cùng đồng thời lắng nghe sự kiện đó. Dữ liệu tương ứng với một sự kiện ít nhất xác định loại sự kiện, nhưng đôi khi cũng bao gồm các thông tin khác như sự kiện xảy ra tại thời điểm nào, đối tượng nào phát động nó…

1.2.           Đơn vị xử lý sự kiện.

Mỗi đơn vị xử lý sự kiện (event handler) đơn giản là một phương thức (hàm) nhận đầu vào từ một thiết bị như chuột hay bàn phím và thực hiện một việc nào đó để phản ứng lại với một sự kiện xảy ra trên thiết bị đó.

private void ButtonOkClicked(object sender, RoutedEventArgs e)

{
this. Close ( ) ; / / đóng hành lang cửa số hiện thời
}
Thực chất, có hai bước cần triển khai để giải quyết và xử lý một sự kiện :
1 – Liên kết đơn vị chức năng giải quyết và xử lý sự kiện với tinh chỉnh và điều khiển ( nút bấm, trường văn bản, thực đơn … ), nơi sự kiện tương ứng được phát động .
2 – Viết mã lệnh trong đơn vị chức năng xử lý sự kiện để lập trình những việc làm phản ứng lại với sự kiện .
Có hai cách để link một sự kiện với một đơn vị chức năng giải quyết và xử lý sự kiện. Bạn hoàn toàn có thể dùng ( 1 ) một môi trường tự nhiên tăng trưởng tích hợp ( IDE ) như Expression Blend hoặc WPF Designer của Visual Studio ( cách trực quan ) ; hoặc ( 2 ) viết mã lệnh trực tiếp .

1.2.1.     Cách liên kết trực quan.

Để link theo cách này, ta cần có những công cụ phong cách thiết kế giao diện GUI dành cho WPF ví dụ điển hình như Expression Blend hoặc WPF Designer của Visual Studio. Với những công cụ này, với mỗi phần từ UI trên giao diện ta có hành lang cửa số liệt kế những sự kiện. Với mỗi sự kiện, ta hoàn toàn có thể phân định đơn vị chức năng giải quyết và xử lý sự kiện bằng cách khai báo tên hàm giải quyết và xử lý ( không gồm đối số ) bên cạnh sự kiện ta muốn bắt và giải quyết và xử lý. Hình 6.1 minh hoạ việc khai báo hàm xử lý sự kiện ButtonOkClicked ứng với sự kiện Click của nút bấm btnOK sử dụng Expression Blend .

Bai_4

Sau khi khai báo, ta nhấn Enter, thiên nhiên và môi trường sẽ tự động hóa tạo sinh và chuyển ta đến khuôn rỗng của hàm xử lý sự kiện có tên giống với tên ta đã đặt cho đơn vị chức năng giải quyết và xử lý sự kiện khi khai báo, và với list tham số ngầm định tương ứng với loại sự kiện. Nhiệm vụ của người lập trình lúc này là viết mã lệnh thực thi những hành vi phản ứng với sự kiện bên trong hàm giải quyết và xử lý này. Trong ví dụ về nút bấm trên, khuôn dạng tự sinh của hàm giải quyết và xử lý sẽ là :

private void ButtonOkClicked(object sender, RoutedEventArgs e)

{
/ / viết mã giải quyết và xử lý vào đây
}
Khi nhìn lại mã XAML tương ứng, ta sẽ thấy WPF sử dụng XAML để khai báo link giữa sự kiện mà hàm xử lý sự kiện như thế nào :

           

           

Kết quả khi chạy chương trình :

Bai_4

Cây trực quan tương ứng sẽ là :

Bai_4

1.3.2.     Sự kiện có định tuyến

Về mặt công dụng, sự kiện có định tuyến là một loại sự kiện hoàn toàn có thể kích hoạt nhiều đơn vị chức năng xử lý sự kiện thuộc về nhiều tinh chỉnh và điều khiển khác nhau trên cây trực quan, chứ không chỉ trên đối tượng người dùng đã phát động sự kiện .
Một ứng dụng WPF nổi bật thường chứa nhiều thành phần UI. Bất kể được tạo ra bằng mã lệnh hay được khai báo bằng XAML, những thành phần này sống sót trong mối quan hệ kiểu cây trực quan với nhau – tạo nên những tuyến quan hệ đi từ thành phần này tới thành phần kia. Theo những tuyến quan hệ đó, có ba phương pháp định tuyến sự kiện : Viral lên ( bubble ), Viral xuống ( tunnel ) và trực tiếp ( direct ) .

  • Lan truyền lên (bubble) là phương thức thường thấy nhất. Nó có nghĩa là một sự kiện sẽ được truyền đi trên cây trực quan từ thành phần nguồn (nơi sự kiện được phát động) cho tới khi nó được xử lý hoặc nó chạm tới nút gốc. Điều này cho phép ta xử lý một sự kiện trên một đối tượng nằm ở cấp trên so với thành phần nguồn. Ví dụ, bạn có thể gắn một hàm xử lý sự kiện Button.Click vào đối tượng Grid có chứa nút bấm thay vì gắn hàm xử lý đó vào bản thân nút bấm. Sự kiện lan truyền lên có tên gọi thể hiện hành động của sự kiện, ví dụ: MouseDown.
  • Sự kiện lan truyền xuống (tunnel) đi theo hướng ngược lại, bắt đầu từ nút gốc và truyền xuống cây trực quan cho tới khi nó được xử lý hoặc chạm tới thành phần gốc của sự kiện đó. Điều này cho phép các thành phần cấp trên có thể chặn sự kiện và xử lý nó trước khi sự kiện đó chạm tới thành phần nguồn (nơi dự định xảy ra sự kiện). Các sự kiện lan truyền xuống có tên được gắn thêm tiền tố Preview, ví dụ,  sự kiện PreviewMouseDown.
  •  Sự kiện trực tiếp (direct) hoạt động giống như sự kiện thông thường trong .NET Framework. Chỉ có một đơn vị xử lý duy nhất sẽ được gắn với sự kiện trực tiếp.

Thông thường, nếu một sự kiện Viral xuống được định nghĩa cho một sự kiện nào đó, đồng thời cũng sẽ có một sự kiện Viral lên tương ứng. Trong trường hợp đó, sự kiện Viral xuống sẽ được phát động trước, khởi đầu từ gốc và chạy xuống tìm kiếm hàm giải quyết và xử lý trên cây trực quan. Một khi nó đã được giải quyết và xử lý hoặc chạm tới thành phần nguồn, sự kiện Viral lên sẽ được phát động, Viral từ thành phần nguồn đi ngược lên để tìm tới hàm giải quyết và xử lý nó trên cây trực quan. Sự kiện Viral lên hay xuống sẽ không ngừng Viral vì một hàm giải quyết và xử lý nó được gọi. Do vậy, nếu ta muốn dừng quy trình truyền xuống hoặc lên, ta phải lưu lại “ đã giải quyết và xử lý ” cho tham số sự kiện truyền vào, đơn cử :

private void OnChildElementMouseDown(object sender, MouseButtonEventArgs e)

{

            e.Handled = true;

}
Một khi ta đã lưu lại “ đã giải quyết và xử lý ” cho sự kiện ( e. Handled = true ), nó sẽ không được Viral tiếp nữa .

Bai_4

1.3.3.     Các tình huống cơ bản sử dụng sự kiện có định tuyến

Xem thêm  Word Of Mouth là gì? Sức mạnh của những "lời truyền miệng" | Tomorrow Marketers

a. Bao đóng và kết hợp điều khiển 

Nhiều điều khiển và tinh chỉnh trong WPF có cấu trúc nội dung phức tạp. Ví dụ, ta hoàn toàn có thể đặt một hình ảnh bên trong một nút bấm, làm lan rộng ra cây trực quan của nút bấm. Tuy nhiên, hình ảnh thêm vào không được phép phá vỡ chính sách hit-testing, chính sách khiến nút bấm phản ứng với việc nhắp chuột vào trong nó, ngay cả khi người dùng nhắp chuột vào những px là một phần của hình ảnh thêm vào .

b. Các điều khiển sử dụng cùng một đơn vị xử lý sự kiện 

Trong Windows Forms, có trường hợp ta cần gán nhiều lần cùng một đơn vị chức năng giải quyết và xử lý để giải quyết và xử lý những sự kiện thuộc vào nhiều thành phần khác nhau. Sự kiện có định tuyến được cho phép ta gán đơn vị chức năng giải quyết và xử lý chỉ một lần trong trường hợp đó. Như trong ví dụ đã nêu trong đoạn mã XAML, sau đây là hàm giải quyết và xử lý tương ứng :

private void CommonClickHandler(object sender, RoutedEventArgs e)

{

            FrameworkElement feSource = e.Source as FrameworkElement;

            switch (feSource.Name)

{
case “ YesButton ” :
/ / do something here …
break ;
case “ NoButton ” :
/ / do something …
break ;
case “ CancelButton ” :
/ / do something …
break ;
}

            e.Handled = true;

}

c. Xử lý lớp: 

Sự kiện có định tuyến được cho phép một đơn vị chức năng giải quyết và xử lý tĩnh ( static ) được định nghĩa trong lớp. Đơn vị giải quyết và xử lý lớp này có thời cơ giải quyết và xử lý một sự kiện trước khi một đơn vị chức năng giải quyết và xử lý gắn với đối tượng người tiêu dùng đơn cử nào đó của lớp hoàn toàn có thể .

d. Tham chiếu đến một sự kiện mà không bị hiện tượng phản xạ: 

Các kỹ thuật markup và mã lệnh yên cầu phải có cách để định danh một sự kiện. Một sự kiện có định tuyến tạo ra trường RoutedEvent như một định danh, phân phối một kỹ thuật định danh sự kiện mạnh mà không yên cầu hiện tượng kỳ lạ phản xạ tĩnh hoặc run-time .

1.3.4.     Ví dụ về sự kiện định tuyến.

Form chỉ gồm có một StackPanel chứa 2 Button và 1 TextBlock có tên xác lập. StackPanel được phân định bắt sự kiện Click trên hai nút bấm nằm trong nó. Nhiệm vụ của đơn vị chức năng xử lý sự kiện Click là cho biết đối tượng người tiêu dùng nào đã xử lý sự kiện Click, sự kiện Click phát ra từ loại đối tượng người tiêu dùng nào, tên gọi là gì nào, và loại Viral định tuyến đã được thực thi. Các thông tin trên được đưa vào nội dung của TextBlock và hiển thị lên màn hình hiển thị sau mỗi sự kiện Click .
Đoạn mã XAML khai báo giao diện như sau :

xmlns = ” http://schemas.microsoft.com/winfx/2006/xaml/presentation ” ;
xmlns : x = ” http://schemas.microsoft.com/winfx/2006/xaml ” ;
Title = ” MainWindow ” Height = ” 350 ″ Width = ” 525 ″ >

   

        Trong đó, có bắt sự kiện Click của Button và giải quyết và xử lý qua hàm HandleClick – >

       

– Khai báo tạo lập Button 1 –

           

– Khai báo tạo lập Button 2 –

           

– Khai báo tạo lập TextBlock tàng trữ và hiển thị hiệu quả –

           

Bai_4

Đoạn mã lệnh C # cho hàm HandleClick để xử lý sự kiện Click :
using System ;
using System. Collections. Generic ;
using System. Linq ;
using System. Text ;
using System. Windows ;

using System.Windows.Controls;

using System. Windows. Data ;
using System. Windows. Documents ;
using System. Windows. Input ;
using System. Windows. Media ;
using System. Windows. Media. Imaging ;
using System. Windows. Navigation ;
using System. Windows. Shapes ;
namespace WPF_Lessons6
{

    ///

/ / / Interaction logic for MainWindow. xaml
/ / /
public partial class MainWindow : Window
{
public MainWindow ( )
{
InitializeComponent ( ) ;
}
/ / Dùng một StringBuilder để tàng trữ thông tin tác dụng
StringBuilder eventstr = new StringBuilder ( ) ;
/ / Đơn vị xử lý sự kiện Click của Button

        private void HandleClick(object sender, RoutedEventArgs args)

{
/ / Lấy thông tin về đối tượng người tiêu dùng xử lý sự kiện Click

            FrameworkElement frame=(FrameworkElement)sender;

eventstr. Append ( “ Sự kiện được giải quyết và xử lý bởi đối tượng người tiêu dùng có tên : “ ) ;

            eventstr.Append(frame.Name);

eventstr. Append ( “ \ n ” ) ;
/ / Lấy thông tin về nguồn phát ra sự kiện CLick :

            FrameworkElement frame2 =(FrameworkElement)args.Source;

/ / + Loại thành phần UI ;

            eventstr.Append(args.Source.GetType().ToString());

/ / + Định danh ;
eventstr. Append ( “ Với tên gọi : “ ) ;

            eventstr.Append(frame2.Name);

eventstr. Append ( “ \ n ” ) ;
/ / Lấy thông tin về phương pháp d9inh6 tuyến
eventstr. Append ( “ Sự kiện về phương pháp định tuyến : “ ) ;

            eventstr.Append(args.RoutedEvent.RoutingStrategy);

eventstr. Append ( “ \ n ” ) ;
/ / Đưa thông tin ra màn hình hiển thị
Results. Text = eventstr. ToString ( ) ;
}
}
}

2.   Lệnh (Command) trong WPF

2.1.           Những khái niệm chính trong hệ thống lệnh của WPF

Mô hình lệnh trong WPF hoàn toàn có thể được chia thành bốn khái niệm chính : lệnh, nguồn lệnh, đích lệnh, và link lệnh, trong đó :
– Lệnh là hành vi được triển khai
– Nguồn lệnh là đối tượng người dùng phát động lệnh
– Đích lệnh là đối tượng người dùng mà lệnh ảnh hưởng tác động lên
– Liên kết lệnh là đối tượng người dùng ánh xạ logic thực thi lệnh với lệnh
2.2. Lệnh có định tuyến
Sự độc lạ giữa lệnh có định tuyến và sự kiện có định tuyến là cách mà lệnh được dẫn đường từ nơi phát động lệnh ( nguồn lệnh ) tới nơi giải quyết và xử lý lệnh ( đích lệnh ). Trong quy mô lệnh có định tuyến, sự kiện có định tuyến được sử dụng dưới dạng những thông tin giữa giữa nguồn lệnh vào đích lệnh ( trải qua link lệnh ) .
Trong một thời gian nhất định, chỉ có một đơn vị chức năng giải quyết và xử lý lệnh ( gắn với đích lệnh ) sẽ được thực sự kích hoạt ( Đơn vị giải quyết và xử lý lệnh hoạt động giải trí ). Đơn vị giải quyết và xử lý lệnh hoạt động giải trí được xác lập bằng việc tích hợp giữa vị trí của nguồn lệnh và đích lệnh trên cây, và đâu là thành phần UI đang nhận được focus. Khi lệnh được phát đi, sự kiện có định tuyến sẽ được sử dụng để gọi đến đơn vị chức năng giải quyết và xử lý lệnh hoạt động giải trí, để hỏi xem lệnh này có được được cho phép không ( trải qua phương pháp CanExecute ), cũng như thực thi logic hành vi ( trải qua phát động phương pháp Executed ) .
Thông thường, nơi phát lệnh sẽ tìm link lệnh giữa vị trí của nó trên cây trực quan và nút gốc của cây trực quan. Nếu nó tìm thấy một link lệnh như vậy, đơn vị chức năng giải quyết và xử lý lệnh tương ứng sẽ xác lập lệnh này có được được cho phép thực thi không. Nếu như lệnh được gắn với một tinh chỉnh và điều khiển trên thanh công cụ hay menu, thì một vài bước logic thêm sẽ được thực thi để tìm dọc theo đường đi trên cây trực quan từ nút gốc tơi thành phần đang nhận được focus để tìm kiếm một link lệnh .
Một điểm quan trọng cần hiểu về việc định tuyến trong lệnh có định tuyến của WPF là một khi một đơn vị chức năng giải quyết và xử lý lệnh đã được kích hoạt, sẽ không có đơn vị chức năng giải quyết và xử lý nào khác được gọi .

Xem thêm  Top 18 family is the best là gì hay nhất 2022

2.3.           Một ví dụ về sử dụng lệnh trong WPF

Đoạn mã sau sẽ vô hiệu hoá mục Delete trên cơ sở có một mục được chọn trong list người mua hay không .
private void HandleMenus ( )
{

menuDelete.IsEnabled = lsbCustomers.SelectedItem != null;

}
Đây là cách thường thì để đồng bộ hoá việc được cho phép hay vô hiệu một mục menu hay nút bấm ứng với một điều kiện kèm theo nào đó. Để đạt tiềm năng đã nêu của đầu bài, đoạn mã trên hoàn toàn có thể được gọi trong đơn vị chức năng xử lý sự kiện SelectionChanged của ListBox như sau :

private void lsbCustomers_SelectionChanged(object sender,SelectionChangedEventArgs e)

{
HandleMenus ( ) ;
}
Cách giải quyết và xử lý dựa trên sự kiện kiểu này là thông thường khi trên form chỉ có một ListBox. Tuy nhiên, khi form trở nên phức tạp hơn, ví dụ chứa 2 ListBox, khi đó việc giải quyết và xử lý theo cách trên trở nên phức tạp. Trở lại ví dụ, giả sử ta có thêm một ListBox có chứa list những loại sản phẩm ( có tên lsbProducts ). Cả hai ListBox chứa tên người mua và tên mẫu sản phẩm đều chịu ảnh hưởng tác động của mục Delete khi chúng nhận được focus và một trong những tên được chọn. Trong trường hợp này, để xét xem mục Delete nên bị vô hiệu hoá hay không, điều kiện kèm theo kiểm tra trở nên phức tạp hơn :
private void HandleMenus ( )
{
menuDelete. IsEnabled =
( lsbCustomers. SelectedItem ! = null và và
( ( ListBoxItem ) lsbCustomers. SelectedItem ). IsFocused ) | |
( lsbProducts. SelectedItem ! = null và và
( ( ListBoxItem ) lsbProducts. SelectedItem ). IsFocused ) ;
}
Đồng thời, cũng nhu yếu thêm mã lệnh so với việc xử lý sự kiện Click lên mục Delete trên menu : Ta phải xác lập ListBox nào bị tác động ảnh hưởng :

private void menuDelete_Click(object sender, RoutedEventArgs e)

{
if ( lsbCustomers. SelectedItem ! = null và và
( ( ListBoxItem ) lsbCustomers. SelectedItem ). IsFocused )
lsbCustomers. Items. Remove ( lsbCustomers. SelectedItem ) ;
else if ( lsbProducts. SelectedItem ! = null và và
( ( ListBoxItem ) lsbProducts. SelectedItem ). IsFocused )
lsbProducts. Items. Remove ( lsbProducts. SelectedItem ) ;
}

2.4.           Lệnh tự tạo

Tự tạo những lệnh của riêng bạn trong nhiều trường hợp là thiết yếu. Việc này cũng không quá phức tạp trong WPF. Để làm được điều này, lớp lệnh tự tạo phải hiện thực hoá giao diện ICommand. Tuy nhiên, ta hoàn toàn có thể dùng lớp RoutedUICommand là lớp có sẵn trong framework đã hiện thực hoá tốt giao diện ICommand. Ví dụ, sau đây là cách tạo nên một lệnh được cho phép chèn thêm một người mua .
Đoạn mã ví dụ như sau :
namespace Lesson6
{
public static class MyCommands
{
static MyCommands ( )
{
InsertCustomer = new RoutedUICommand (
“ Insert Customer ”, “ InsertCustomer ” ,
typeof ( MyCommands ) ) ;
}
public readonly static RoutedUICommand InsertCustomer ;
}
}

Chia sẻ:

Thích bài này:

Thích

Đang tải …

Xem thêm bài viết thuộc chuyên mục: Tin tổng hợp

Related Articles

Trả lời

Email của bạn sẽ không được hiển thị công khai.

Back to top button