这个路由事件,为何还要路由啊

这个路由事件,为什么还要路由啊?
本帖最后由 df4343t 于 2015-04-08 10:25:21 编辑
一个继承自ComboBox的自定义控件MyComboBox:

public class MyComboBox : ComboBox
{
    static MyComboBox()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(MyComboBox), new FrameworkPropertyMetadata(typeof(MyComboBox)));
    }
    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);
        e.Handled = true;
    }
}

窗体:

 <local:MyComboBox SelectionChanged="ComboBox_SelectionChanged">
          <ComboBoxItem Content="张三"/>
          <ComboBoxItem Content="李四"/>
  </local:MyComboBox>


private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    MessageBox.Show("ghgh");
}

在MyComboBox类中,在类处理程序OnSelectionChanged中,已经将Handled设为了true,可是为什么在窗体中的,改变MyComboBox的选定项,还是不断地弹出对话框呢?也就是说,实例事件处理程序仍然是执行了的,这是为什么呢?
------解决思路----------------------
base.OnSelectionChanged(e);
你都继承这个了,怎么可能不执行?
------解决思路----------------------


    protected override void OnSelectionChanged(SelectionChangedEventArgs e)
    {
        base.OnSelectionChanged(e);
        e.Handled = true;
    }

你这明明是先执行base.OnSelectionChanged(e); 
后e.Handled = true;

你还是去掉base.OnSelectionChanged(e); 这行吧


 



------解决思路----------------------
引用:
Quote: 引用:

base.OnSelectionChanged(e);
你都继承这个了,怎么可能不执行?

base.OnSelectionChanged(e);这个通常都是要这么做得呀,况且再怎么base,也是要等到类处理程序执行完之后,才会轮到实例处理程序的啊,而在类处理程序的最后是把Handled设为了true的,这点是不容改变的吧。

base.OnSelectionChanged(e);这个方法内部会去执行事件……
------解决思路----------------------
你调试一下,看有没有执行MyComboBox::OnSelectionChanged函数,也就是 你的e.handled=true这一句有没有执行
------解决思路----------------------
你的代码不全,看不清楚。


private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    MessageBox.Show("ghgh");
}
 

这是ComboBox_SelectionChanged, 不是 MyComboBox_SelectionChanged 吧?

你后来的可是CustomControl1_MouseLeftButtonDown,应该对应MyComboBox_SelectionChanged 的。



------解决思路----------------------
这两个事件是完全不同的事件,你可以查看msdn,MouseLeftButtonDown是在UIElement上存在的冒泡事件,由系统自动处理事件调用,该事件未在Control里做过任何重载,所以base调用都是空的,不执行任何动作,OnMouseLeftButtonDown的执行优先于注册的事件,只要在OnMouseLeftButtonDown的任何位置设置e.Handled = true,注册的事件就不执行了。但是那个OnSelectionChanged却不同,是ComboBox特有的事件,其实现在基类ComboBox中做过定义,并在基类的OnSelectionChanged方法中调用了用户注册事件,因此你优先去执行那个base.OnSelectionChanged,势必就先执行了用户注册事件。
总结一下,好的编程方法就是,如果你要取消,请在调用base.Onxxx之前,先设置e.Handled = true,那样无论哪种情况,结果都一样了。
------解决思路----------------------
另外你还要看看这个路由事件的方向,是冒泡的还是隧道的,如果是冒泡的,则方向从本控件路由到逻辑树的根控件,首先收到事件的是本控件,如果是隧道的,则从逻辑树的根控件一路路由到本控件,首先收到的是逻辑树的根控件。