这个路由事件,为何还要路由啊
这个路由事件,为什么还要路由啊?
一个继承自ComboBox的自定义控件MyComboBox:
窗体:
在MyComboBox类中,在类处理程序OnSelectionChanged中,已经将Handled设为了true,可是为什么在窗体中的,改变MyComboBox的选定项,还是不断地弹出对话框呢?也就是说,实例事件处理程序仍然是执行了的,这是为什么呢?
------解决思路----------------------
base.OnSelectionChanged(e);
你都继承这个了,怎么可能不执行?
------解决思路----------------------
你这明明是先执行base.OnSelectionChanged(e);
后e.Handled = true;
你还是去掉base.OnSelectionChanged(e); 这行吧
------解决思路----------------------
base.OnSelectionChanged(e);这个方法内部会去执行事件……
------解决思路----------------------
你调试一下,看有没有执行MyComboBox::OnSelectionChanged函数,也就是 你的e.handled=true这一句有没有执行
------解决思路----------------------
你的代码不全,看不清楚。
这是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,那样无论哪种情况,结果都一样了。
------解决思路----------------------
另外你还要看看这个路由事件的方向,是冒泡的还是隧道的,如果是冒泡的,则方向从本控件路由到逻辑树的根控件,首先收到事件的是本控件,如果是隧道的,则从逻辑树的根控件一路路由到本控件,首先收到的是逻辑树的根控件。
一个继承自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); 这行吧
------解决思路----------------------
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,那样无论哪种情况,结果都一样了。
------解决思路----------------------
另外你还要看看这个路由事件的方向,是冒泡的还是隧道的,如果是冒泡的,则方向从本控件路由到逻辑树的根控件,首先收到事件的是本控件,如果是隧道的,则从逻辑树的根控件一路路由到本控件,首先收到的是逻辑树的根控件。