zoukankan      html  css  js  c++  java
  • 路由事件

    基础点

    WPF支持直接事件,如 winform样直达事件。

    最重要的是wpf支持路由事件,路由是通过“可视树”来传递的,而非逻辑树。

    一个事件可以由多个事件处理器来处理(多播),一个事件处理器可以响应多个事件。

    一个元素添加了事件侦听器,就不关心是谁触发的。

    事件可以由触发元素一层一层向外传递,或由页面最外层一直往里传递,而非由元素开始才向内传。

    事件的e.OriginalSource 为事件的可视树为源头,e.Source为逻辑树源头

    事件就是定义一个路由事件,然后元素侦听此事件就行,相当于多播

     为元素添加事件侦听

      public partial class eventsim : Window

        {

            public eventsim()

            {

                InitializeComponent();

                //主要是通过AddHandler来添加对事件的侦听

                this.root.AddHandler(Button.ClickEvent, new RoutedEventHandler(buttonClick));

            }

            private void buttonClick(object sender, RoutedEventArgs e)

            {

                //使用e.OriginalSource获取触发者,而不是sender

                var source = e.OriginalSource as Button;

                MessageBox.Show(source.Name);

            }

        }

    xaml里的写法

    <Grid x:Name="root" Button.Click="buttonClick">

    自定义路由事件

    的写法

    <Grid x:Name="grid1"  local:TimeButton.ReportTime="ReportTimeHandler">

            <Grid x:Name="grid2"  local:TimeButton.ReportTime="ReportTimeHandler">

                <Grid x:Name="grid3"  local:TimeButton.ReportTime="ReportTimeHandler">

         <local:TimeButton x:Name="time" Content="报时"  local:TimeButton.ReportTime="ReportTimeHandler"></local:TimeButton>

                    <ListBox x:Name="listBox" H />

                </Grid>  

            </Grid>

        </Grid>

     public partial class eventsim : Window

        {

            public eventsim()

            {

                InitializeComponent();

            }

            private void ReportTimeHandler(object sender, TimeRouteEventArgs e)

            {

                var ele = sender as FrameworkElement;

                listBox.Items.Add(string.Format("事件到达{0},时间{1}",ele.Name,e.DateTime));

            }

             

        }

        //自定义事件触发后所携带的消息

        public class TimeRouteEventArgs : RoutedEventArgs

        {

            public TimeRouteEventArgs(RoutedEvent routedEvent, object source)

                :base(routedEvent, source)

            {   }

            public DateTime DateTime { get; set; }

        }

        //自定义一个按钮

        public class TimeButton : Button

        {

            //注册“报告时间”路由事件

            //变更名为"XXEvent",注册后事件名则为“XX”,这是默认的格式,要遵守

            public static readonly RoutedEvent ReportTimeEvent =

                EventManager.RegisterRoutedEvent("ReportTime", RoutingStrategy.Bubble, typeof(EventHandler<TimeRouteEventArgs>), typeof(TimeButton));

            //CLR事件包装器,就是给别人注册此事件使用

            public event RoutedEventHandler ReportTime

            {

                add { this.AddHandler(ReportTimeEvent, value); }

                remove { this.RemoveHandler(ReportTimeEvent, value); }

            }

            //激发路由事件,借助Click事件

            protected override void OnClick()

            {

                base.OnClick();//保留原始功能

                TimeRouteEventArgs arg = new TimeRouteEventArgs(ReportTimeEvent,this);

                arg.DateTime = DateTime.Now;

                //使用RaiseEvent激发事件

                this.RaiseEvent(arg);

            }

        }

    参数说明:

    public static readonly RoutedEvent ReportTimeEvent =

                EventManager.RegisterRoutedEvent("ReportTime", RoutingStrategy.Bubble, typeof(EventHandler<TimeRouteEventArgs>), typeof(TimeButton));

    第一个:注册的事件名,一般为变更名不加Event

    第二个:传递方向,Bubble由激发元素向外传,Tunnel由树根向内传,Direct直接事件

    第三个:事件的处理器类型

    第四个:事件的宿主

    停止事件继续传递

          private void ReportTimeHandler(object sender, TimeRouteEventArgs e)

            {

                var ele = sender as FrameworkElement;

                if (ele.Name == "grid2")

                    e.Handled = true;//停止继续传递

                listBox.Items.Add(string.Format("事件到达{0},时间{1}",ele.Name,e.DateTime));

            }

    附加事件

    路由事件的宿主是可视元素,而附加事件的宿主都是不可视元素,附加事件的触发还是得依靠元素的RaiseEvent。

    例子:一个Student类,当名称变更时的事件

    public partial class eventsim : Window

        {

            public eventsim()

            {

                InitializeComponent();

                //为元素grid1添加(student7的NageChange变更事件)侦听

                Student7.AddNameChangeHandler(grid1, new RoutedEventHandler(NameChangeEvenHandler));

            }

            //捕获变更后的事件处理器

            private void NameChangeEvenHandler(object sender,  RoutedEventArgs e)

            {

                MessageBox.Show((e.OriginalSource as Student7).Id.ToString());

            } 

            private void button_Click(object sender, RoutedEventArgs e)

            {

                Student7 stu = new Student7() { Id=1,Name="111"};

                stu.Name = "222";

           RoutedEventArgs arg = new RoutedEventArgs(Student7.NameChangeEvent, stu);//注意这里的source为stu,而非this 

                this.button1.RaiseEvent(arg);

            }

        }

        public class Student7

        {

            public int Id { get; set; }

            public string Name { get; set; }

            //定义路由事件

            public static readonly RoutedEvent NameChangeEvent =

              EventManager.RegisterRoutedEvent("NameChange", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Student7));

            //附加事件不能像路由事件那样添加CLR事件包装器,只能分开两个方法写

            //为界面元素添加路由事件侦听,注意命名规则

            public static void AddNameChangeHandler(DependencyObject d, RoutedEventHandler h)

            {

                UIElement e = d as UIElement;

                if (e != null)

                {

                    e.AddHandler(Student7.NameChangeEvent, h);

                }

            }

            //移除侦听

            public static void RemoveNameChangeHandler(DependencyObject d, RoutedEventHandler h)

            {

                UIElement e = d as UIElement;

                if (e != null)

                {

                    e.RemoveHandler(Student7.NameChangeEvent, h);

                }

            }

        }

  • 相关阅读:
    【持续更新】dp优化浅谈:实现篇
    【持续更新】dp优化浅谈:理论篇
    利用普通生成函数解斐波那契数列的通项问题
    【讲稿】动态规划基础4
    多项式板子(待完善)
    快速傅里叶变换学习笔记
    非阻塞同步算法实战(四)- 计数器定时持久化
    您还有心跳吗?超时机制分析(java)
    [分享]正则文本替换器(已开源)
    MySql大表分页(附独门秘技)
  • 原文地址:https://www.cnblogs.com/evemen/p/6239326.html
Copyright © 2011-2022 走看看