WPF - เหตุการณ์ที่กำหนดเส้นทาง

routed eventเป็นเหตุการณ์ประเภทหนึ่งที่สามารถเรียกใช้ตัวจัดการกับผู้ฟังหลายคนในโครงสร้างองค์ประกอบแทนที่จะเป็นเพียงวัตถุที่ยกเหตุการณ์ โดยพื้นฐานแล้วเป็นเหตุการณ์ CLR ที่สนับสนุนโดยอินสแตนซ์ของคลาส Routed Event มีการลงทะเบียนกับระบบเหตุการณ์ WPF RoutedEvents มีกลยุทธ์การกำหนดเส้นทางหลักสามแบบซึ่งมีดังต่อไปนี้ -

  • เหตุการณ์โดยตรง
  • เหตุการณ์ฟองสบู่
  • เหตุการณ์อุโมงค์

เหตุการณ์โดยตรง

เหตุการณ์โดยตรงคล้ายกับเหตุการณ์ในรูปแบบของ Windows ซึ่งเกิดขึ้นโดยองค์ประกอบที่เหตุการณ์นั้นเกิดขึ้น

ไม่เหมือนกับเหตุการณ์ CLR มาตรฐานเหตุการณ์ที่กำหนดเส้นทางโดยตรงรองรับการจัดการคลาสและสามารถใช้ในตัวตั้งค่าเหตุการณ์และทริกเกอร์เหตุการณ์ภายในสไตล์การควบคุมแบบกำหนดเองของคุณ

ตัวอย่างที่ดีของเหตุการณ์โดยตรงคือเหตุการณ์ MouseEnter

เหตุการณ์ฟองสบู่

เหตุการณ์ที่เดือดปุด ๆ เริ่มต้นด้วยองค์ประกอบที่เป็นจุดเริ่มต้นของเหตุการณ์ จากนั้นจะเดินทางขึ้นต้นไม้ภาพไปยังองค์ประกอบที่อยู่บนสุดในแผนผังภาพ ดังนั้นใน WPF องค์ประกอบที่อยู่บนสุดน่าจะเป็นหน้าต่าง

เหตุการณ์อุโมงค์

ตัวจัดการเหตุการณ์บนรากขององค์ประกอบจะถูกเรียกใช้จากนั้นเหตุการณ์จะเดินทางไปตามแผนผังภาพไปยังโหนดลูกทั้งหมดจนกว่าจะถึงองค์ประกอบที่เหตุการณ์นั้นเกิดขึ้น

ความแตกต่างระหว่างเหตุการณ์ที่มีฟองและการสร้างอุโมงค์คือเหตุการณ์การสร้างอุโมงค์จะเริ่มต้นด้วยการแสดงตัวอย่างเสมอ

ในแอปพลิเคชัน WPF มักใช้เหตุการณ์เป็นคู่ทันเนล / บับเบิ้ล ดังนั้นคุณจะมีตัวอย่าง MouseDown และเหตุการณ์ MouseDown

ด้านล่างนี้เป็นตัวอย่างง่ายๆของเหตุการณ์ที่กำหนดเส้นทางซึ่งปุ่มและสามบล็อกข้อความถูกสร้างขึ้นด้วยคุณสมบัติและเหตุการณ์บางอย่าง

<Window x:Class = "WPFRoutedEvents.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   Title = "MainWindow" Height = "450" Width = "604" ButtonBase.Click  = "Window_Click" >
	
   <Grid> 
      <StackPanel Margin = "20" ButtonBase.Click = "StackPanel_Click">
		
         <StackPanel Margin = "10"> 
            <TextBlock Name = "txt1" FontSize = "18" Margin = "5" Text = "This is a TextBlock 1" /> 
            <TextBlock Name = "txt2" FontSize = "18" Margin = "5" Text = "This is a TextBlock 2" /> 
            <TextBlock Name = "txt3" FontSize = "18" Margin = "5" Text = "This is a TextBlock 3" /> 
         </StackPanel> 
			
         <Button Margin = "10" Content = "Click me" Click = "Button_Click" Width = "80"/> 
      </StackPanel> 
   </Grid> 
	
</Window>

นี่คือรหัส C # สำหรับการใช้งานเหตุการณ์คลิกสำหรับปุ่ม StackPanel และ Window

using System.Windows; 
 
namespace WPFRoutedEvents { 
   /// <summary> 
      /// Interaction logic for MainWindow.xaml 
   /// </summary>
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void Button_Click(object sender, RoutedEventArgs e) { 
         txt1.Text = "Button is Clicked"; 
      } 
		
      private void StackPanel_Click(object sender, RoutedEventArgs e) { 
         txt2.Text = "Click event is bubbled to Stack Panel"; 
      } 
		
      private void Window_Click(object sender, RoutedEventArgs e) { 
         txt3.Text = "Click event is bubbled to Window"; 
      }
		
   } 
}

เมื่อคุณคอมไพล์และรันโค้ดด้านบนจะมีหน้าต่างดังต่อไปนี้ -

เมื่อคุณคลิกที่ปุ่มบล็อกข้อความจะได้รับการอัปเดตดังที่แสดงด้านล่าง

หากคุณต้องการหยุดเหตุการณ์ที่กำหนดเส้นทางในระดับใดระดับหนึ่งคุณจะต้องตั้งค่า e.Handled = true;

มาเปลี่ยนไฟล์ StackPanel_Click เหตุการณ์ดังภาพด้านล่าง -

private void StackPanel_Click(object sender, RoutedEventArgs e) { 
   txt2.Text = "Click event is bubbled to Stack Panel"; 
   e.Handled = true; 
}

เมื่อคุณคลิกที่ปุ่มคุณจะสังเกตได้ว่าเหตุการณ์การคลิกจะไม่ถูกส่งไปยังหน้าต่างและจะหยุดที่สแต็กพาเนลและบล็อกข้อความrd 3 จะไม่ได้รับการอัปเดต

กำหนดเส้นทางเหตุการณ์ที่กำหนดเอง

ใน. NET framework ยังสามารถกำหนดเหตุการณ์ที่กำหนดเส้นทางเองได้ คุณต้องทำตามขั้นตอนที่ระบุด้านล่างเพื่อกำหนดเหตุการณ์ที่กำหนดเส้นทางเองใน C #

  • ประกาศและลงทะเบียนเหตุการณ์ที่กำหนดเส้นทางของคุณด้วยระบบเรียก RegisterRoutedEvent

  • ระบุกลยุทธ์การกำหนดเส้นทางเช่น Bubble, Tunnel หรือ Direct

  • ระบุตัวจัดการเหตุการณ์

ลองดูตัวอย่างเพื่อทำความเข้าใจเพิ่มเติมเกี่ยวกับเหตุการณ์ที่กำหนดเส้นทางเอง ทำตามขั้นตอนด้านล่าง -

  • สร้างโปรเจ็กต์ WPF ใหม่ด้วย WPFCustomRoutedEvent

  • คลิกขวาที่โซลูชันของคุณแล้วเลือกเพิ่ม> รายการใหม่ ...

  • กล่องโต้ตอบต่อไปนี้จะเปิดขึ้นตอนนี้เลือก Custom Control (WPF) และตั้งชื่อ MyCustomControl.

  • คลิก Add และคุณจะเห็นว่าไฟล์ใหม่สองไฟล์ (Themes / Generic.xaml และ MyCustomControl.cs) จะถูกเพิ่มเข้าไปในโซลูชันของคุณ

โค้ด XAML ต่อไปนี้ตั้งค่าสไตล์สำหรับคอนโทรลแบบกำหนดเองในไฟล์ Generic.xaml

<ResourceDictionary 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent">
	
   <Style TargetType = "{x:Type local:MyCustomControl}"> 
      <Setter Property = "Margin" Value = "50"/> 
      <Setter Property = "Template"> 
         <Setter.Value> 
            <ControlTemplate TargetType = "{x:Type local:MyCustomControl}">
				
               <Border Background = "{TemplateBinding Background}" 
                  BorderBrush = "{TemplateBinding BorderBrush}" 
                  BorderThickness = "{TemplateBinding BorderThickness}"> 
                  <Button x:Name = "PART_Button" Content = "Click Me" /> 
               </Border> 
					
            </ControlTemplate> 
         </Setter.Value> 
      </Setter> 
   </Style> 
	
</ResourceDictionary>

ด้านล่างนี้คือรหัส C # สำหรับไฟล์ MyCustomControl class ซึ่งสืบทอดมาจากไฟล์ Control class ซึ่งเหตุการณ์ที่กำหนดเส้นทางเอง Click ถูกสร้างขึ้นสำหรับคอนโทรลแบบกำหนดเอง

using System.Windows; 
using System.Windows.Controls;  

namespace WPFCustomRoutedEvent { 

   public class MyCustomControl : Control { 
	
      static MyCustomControl() { 
         DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomControl), 
            new FrameworkPropertyMetadata(typeof(MyCustomControl))); 
      } 
		
      public override void OnApplyTemplate() { 
         base.OnApplyTemplate();
			
         //demo purpose only, check for previous instances and remove the handler first 
         var button  =  GetTemplateChild("PART_Button") as Button; 
         if (button ! =  null) 
         button.Click + =  Button_Click;  
      } 
		
      void Button_Click(object sender, RoutedEventArgs e) { 
         RaiseClickEvent(); 
      } 
		
      public static readonly RoutedEvent ClickEvent  =  
         EventManager.RegisterRoutedEvent("Click", RoutingStrategy.Bubble, 
         typeof(RoutedEventHandler), typeof(MyCustomControl)); 
			
      public event RoutedEventHandler Click { 
         add { AddHandler(ClickEvent, value); } 
         remove { RemoveHandler(ClickEvent, value); } 
      } 
		
      protected virtual void RaiseClickEvent() { 
         RoutedEventArgs args = new RoutedEventArgs(MyCustomControl.ClickEvent); 
         RaiseEvent(args); 
      }
		
   } 
}

นี่คือการใช้งานเหตุการณ์ที่กำหนดเส้นทางเองใน C # ซึ่งจะแสดงกล่องข้อความเมื่อผู้ใช้คลิก

using System.Windows;  

namespace WPFCustomRoutedEvent { 
   // <summary> 
      // Interaction logic for MainWindow.xaml
   // </summary> 
	
   public partial class MainWindow : Window { 
	
      public MainWindow() { 
         InitializeComponent(); 
      }  
		
      private void MyCustomControl_Click(object sender, RoutedEventArgs e) { 
         MessageBox.Show("It is the custom routed event of your custom control"); 
      } 
		
   } 
}

นี่คือการนำไปใช้ใน MainWindow.xaml เพื่อเพิ่มการควบคุมแบบกำหนดเองด้วยเหตุการณ์ที่กำหนดเส้นทางคลิก

<Window x:Class = "WPFCustomRoutedEvent.MainWindow" 
   xmlns = "http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:local = "clr-namespace:WPFCustomRoutedEvent"
   Title = "MainWindow" Height = "350" Width = "604"> 
	
   <Grid> 
      <local:MyCustomControl Click = "MyCustomControl_Click" /> 
   </Grid> 
	
</Window>

เมื่อโค้ดด้านบนถูกคอมไพล์และเรียกใช้โค้ดจะสร้างหน้าต่างต่อไปนี้ซึ่งมีคอนโทรลแบบกำหนดเอง

เมื่อคุณคลิกที่คอนโทรลแบบกำหนดเองมันจะสร้างข้อความต่อไปนี้