WPF-关于自定义路由事件与附加事件

一、概念

        消息层层传递,遇到安装有事件侦听器的对象,通过事件处理器响应事件,并决定事件是否继续传递;

二、自定义路由器事件

主要步骤:(与依赖属性相似)

1、声明并注册路由事件;

2、为路由事件添加CLR事件包装器;

3、创建可以激发路由事件的方法;

 1、使用EventManager.RegisterRoutedEvent注册路由事件

public static readonly RoutedEvent DisplayTimeEvent = EventManager.RegisterRoutedEvent(
            "DisplayTime",
            RoutingStrategy.Bubble,
            typeof(EventHandler<DisPlayTimeHanderArgs>),
            typeof(TimeButton));

参数一:路由器名称,与CLR事件包装器名称一致;

参数二:路由事件策略:

Bubble冒泡式:UI树自底端(事件激发)向顶端传递

Tunnel隧道式:树根向事件激发控件传递,与冒泡相反

Direct直达式:模仿CLR直接事件

参数三:指定事件处理器的类型,标签与此参数委托一致;

参数四:指明路由事件的宿主;

RoutedEventArgs常用属性:

Handled,bool类型,为true。不再传递;

Source:表示LogicalTree上的消息源头(传递起点);

OriginalSource:VisualTree上的源头;

2、添加包装器

        public event RoutedEventHandler DisplayTime
        {
            add
            {
                AddHandler(DisplayTimeEvent, value);
            }
            remove
            {
                RemoveHandler(DisplayTimeEvent, value);
            }
        }

3、激发事件的方法 

        protected override void OnClick()
        {
            base.OnClick();
            DisPlayTimeHanderArgs timeHanderArgs = new DisPlayTimeHanderArgs(DisplayTimeEvent, this);
            timeHanderArgs.Time=DateTime.Now;
            this.RaiseEvent(timeHanderArgs);
        }

 示例代码:

    public class TimeButton : Button
    {
        public event RoutedEventHandler DisplayTime
        {
            add
            {
                AddHandler(DisplayTimeEvent, value);
            }
            remove
            {
                RemoveHandler(DisplayTimeEvent, value);
            }
        }
        public static readonly RoutedEvent DisplayTimeEvent = EventManager.RegisterRoutedEvent(
            "DisplayTime",
            RoutingStrategy.Bubble,
            typeof(EventHandler<DisPlayTimeHanderArgs>),
            typeof(TimeButton));
        protected override void OnClick()
        {
            base.OnClick();
            DisPlayTimeHanderArgs timeHanderArgs = new DisPlayTimeHanderArgs(DisplayTimeEvent, this);
            timeHanderArgs.Time = DateTime.Now;
            this.RaiseEvent(timeHanderArgs);
        }
    }
    public class DisPlayTimeHanderArgs : RoutedEventArgs
    {
        public DisPlayTimeHanderArgs(RoutedEvent routed, object source) : base(routed, source)
        {

        }
        public DateTime Time { get; set; }
    }
}

界面代码: 

    <Grid>
        <model:TimeButton x:Name="tbtn" Width="80" Height="80" Background="LightBlue" Content="Time"/>
    </Grid>

主窗口后台代码: 

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.tbtn.AddHandler(TimeButton.DisplayTimeEvent, new RoutedEventHandler(DisplayTimeHander));          
        }

        private void DisplayTimeHander(object sender,RoutedEventArgs e)
        {
           
            FrameworkElement frameworkElement = sender as FrameworkElement;
            DisPlayTimeHanderArgs args = e as DisPlayTimeHanderArgs;
            MessageBox.Show(frameworkElement.Name.ToString()+"\r\n"+ args.Time.ToShortTimeString());
        }
    }

 

 三、附加事件

附加事件是路由事件的一种,但不具备显示在用户界面上的能力,一般存在Binding类、Mouse类、KeyBoard类

注意:非UIElement的派生类,不具有RaiseEvent方法,通过借用其它控件的RaiseEvent发送事件,同理没有AddHandler和RemoveHandler方法,所以通过”借用“的方式为事件进行包装;

示例代码:

    internal class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public static void AddAttanchedHandler(DependencyObject dpo, RoutedEventHandler e)
        {
            UIElement uIElement = dpo as UIElement;
            if (uIElement != null)
            {
                uIElement.AddHandler(AttanchedEvent, e);
            }
        }
        public static void RemoveAttanchedHandler(DependencyObject dpo, RoutedEventHandler e)
        {
            UIElement uIElement = dpo as UIElement;
            if (uIElement != null)
            {
                uIElement.RemoveHandler(AttanchedEvent, e);
            }
        }
        public static readonly RoutedEvent AttanchedEvent =
            EventManager.RegisterRoutedEvent("Attanched", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof(Student));
    }

主窗口后台:

        public MainWindow()
        {
            InitializeComponent();
            sp.AddHandler(Student.AttanchedEvent, new RoutedEventHandler(AttanchedHandler));
            Student.AddAttanchedHandler(this.grd, new RoutedEventHandler(AttanchedHandler));

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Student student = new Student() { Id = 1, Name = "Tom" };
            student.Name = "Auston";
            RoutedEventArgs args = new RoutedEventArgs(Student.AttanchedEvent,student);
            btn.RaiseEvent(args);
        }
        private void AttanchedHandler(object sender,RoutedEventArgs e)
        {
            FrameworkElement frameworkElement = sender as FrameworkElement;
            listbox.Items.Add(frameworkElement.Name+"\t"+(e.OriginalSource as Student).Name);
        }

 Xaml代码:

    <Grid x:Name="grd" >
        <StackPanel Name="sp">
            <ListBox Name="listbox"/>
            <Button Width="80" Name="btn" Height="80" Background="LightGray" Content="OK" Click="Button_Click"/>
        </StackPanel>
    </Grid>

四、附:部分代码段(snippet)

可添加进代码片段管理器,提升工作效率

路由器事件代码段:

public event $type$ $event$
{
    add
    {
        AddHandler($event$Event, value);
    }
    remove
    {
        RemoveHandler($event$Event, value);
    }
}

//Register a RoutedEvent....
public static readonly RoutedEvent $event$Event =
    EventManager.RegisterRoutedEvent("$event$", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof($owner$));

附加事件代码段: 

public static void Add$event$Handler(DependencyObject dpo, RoutedEventHandler e)
{
    UIElement uIElement = dpo as UIElement;
    if (uIElement != null)
    {
        uIElement.AddHandler($event$Event, e);
    }
}

public static void Remove$event$Handler(DependencyObject dpo, RoutedEventHandler e)
{
    UIElement uIElement = dpo as UIElement;
    if (uIElement != null)
    {
        uIElement.RemoveHandler($event$Event, e);
    }
}

//Register a Attanched Event...
public static readonly RoutedEvent $event$Event =
    EventManager.RegisterRoutedEvent("$event$", RoutingStrategy.Bubble, typeof(RoutedEventArgs), typeof($owner$));

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF中,自定义路由事件可以通过以下步骤实现: 1. 定义一个自定义路由事件: ``` public class MyRoutedEvent : RoutedEventArgs { public MyRoutedEvent() : base() { } public MyRoutedEvent(RoutedEvent routedEvent) : base(routedEvent) { } public MyRoutedEvent(RoutedEvent routedEvent, object source) : base(routedEvent, source) { } public string MyEventArgs { get; set; } // 自定义事件参数 public static readonly RoutedEvent MyEvent = EventManager.RegisterRoutedEvent("MyEvent", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MyRoutedEvent)); // 添加路由事件处理程序 public event RoutedEventHandler MyEventHandler { add { AddHandler(MyEvent, value); } remove { RemoveHandler(MyEvent, value); } } // 触发路由事件 public void RaiseMyEvent() { RaiseEvent(new RoutedEventArgs(MyEvent)); } } ``` 在这个例子中,我们定义了一个继承自RoutedEventArgs的类,并添加了一个自定义事件参数MyEventArgs。我们还定义了一个静态只读的MyEvent路由事件,并为它添加了一个路由事件处理程序MyEventHandler。最后,我们实现了一个RaiseMyEvent方法,该方法将触发MyEvent路由事件。 2. 在UI元素中使用自定义路由事件: ``` <Button Content="Click me" Click="Button_Click"/> ``` 在这个例子中,我们将按钮的Click事件绑定到Button_Click方法。在该方法中,我们可以创建一个MyRoutedEvent实例并触发它: ``` private void Button_Click(object sender, RoutedEventArgs e) { MyRoutedEvent myEvent = new MyRoutedEvent(); myEvent.MyEventArgs = "Hello World!"; RaiseEvent(myEvent); } ``` 在这个例子中,我们创建了一个MyRoutedEvent实例,并将MyEventArgs设置为“Hello World!”。然后,我们调用RaiseEvent方法触发MyEvent路由事件。 3. 在父控件中处理自定义路由事件: ``` <Grid local:MyRoutedEvent.MyEvent="Grid_MyEvent"> <!-- 子控件 --> </Grid> ``` 在这个例子中,我们将Grid控件的MyEvent路由事件绑定到Grid_MyEvent方法。在该方法中,我们可以获取到MyEventArgs的值: ``` private void Grid_MyEvent(object sender, RoutedEventArgs e) { MyRoutedEvent myEvent = (MyRoutedEvent)e; string myEventArgs = myEvent.MyEventArgs; // 处理自定义路由事件 } ``` 在这个例子中,我们获取MyRoutedEvent实例,并将其转换为MyRoutedEvent类型。然后,我们可以获取MyEventArgs的值并进行处理。 这就是一个简单的自定义路由事件的实现方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值