代码改变世界

跟着小王学习wpf之路由事件

2011-04-04 00:56  Wang_top  阅读(1047)  评论(3)    收藏  举报

先看一个下测试程序

View Code
class ExmapleRouteEvents : Application
{
static readonly FontFamily fontfam = new FontFamily("Lucida Console");
const string strFormot = "{0,-25}{1,-25}{2,-25}{3,-25}";
StackPanel stackoutput;
DateTime dtlast;
[STAThread]
static void Main(string[] args)
{
ExmapleRouteEvents app
= new ExmapleRouteEvents();
app.Run();
}
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
Window win
= new Window();
win.Title
= "ExmapleRouteEvents";
Grid grid
= new Grid();
win.Content
= grid;
for (int i = 0; i < 2;i++ )
{
RowDefinition row
= new RowDefinition();
row.Height
= GridLength.Auto;
grid.RowDefinitions.Add(row);

//ColumnDefinition col = new ColumnDefinition();
//col.Width = GridLength.Auto;
//grid.ColumnDefinitions.Add(col);
}
RowDefinition row1
= new RowDefinition();
row1.Height
= new GridLength(100, GridUnitType.Star);
grid.RowDefinitions.Add(row1);
Button btn
= new Button();
btn.HorizontalAlignment
= HorizontalAlignment.Center;
btn.Margin
= new Thickness(25);
btn.Padding
= new Thickness(25);
grid.Children.Add(btn);

TextBlock text
= new TextBlock();
text.FontSize
= 24;
text.Text
= win.Title;
btn.Content
= text;


TextBlock Headingtext
= new TextBlock();
Headingtext.FontFamily
= fontfam;
Headingtext.Inlines.Add(
new Underline(new Run(
string.Format(strFormot,"Routed Event","Sender","Source","Original Source"))
));
grid.Children.Add(Headingtext);
Grid.SetRow(Headingtext,
1);

ScrollViewer scroll
= new ScrollViewer();
grid.Children.Add(scroll);
Grid.SetRow(scroll,
2);


stackoutput
= new StackPanel();
scroll.Content
= stackoutput;

UIElement[] els
= { win, grid, btn, text };
foreach (UIElement el in els)
{
el.PreviewKeyDown
+= AllEventshandler;
el.PreviewKeyUp
+= AllEventshandler;
el.PreviewTextInput
+= AllEventshandler;

el.KeyDown
+= AllEventshandler;
el.KeyUp
+= AllEventshandler;
el.TextInput
+= AllEventshandler;


el.PreviewMouseDown
+= AllEventshandler;
el.PreviewMouseUp
+= AllEventshandler;
el.MouseDown
+= AllEventshandler;
el.MouseUp
+= AllEventshandler;


el.StylusDown
+= AllEventshandler;
el.StylusUp
+= AllEventshandler;
el.PreviewStylusDown
+= AllEventshandler;
el.PreviewStylusUp
+= AllEventshandler;

el.AddHandler(Button.ClickEvent,
new RoutedEventHandler(AllEventshandler));
}
win.Show();
}

void AllEventshandler( object sender,RoutedEventArgs args)
{
DateTime dtNow
= DateTime.Now;
if (dtNow-dtlast>TimeSpan.FromMilliseconds(100))
{
stackoutput.Children.Add(
new TextBlock(new Run(" ")));
}
dtlast
= dtNow;
TextBlock text
= new TextBlock();
text.FontFamily
= fontfam;
text.Text
= String.Format(strFormot,
args.RoutedEvent.Name,
TypeWithoutName(sender),
TypeWithoutName(args.Source),
TypeWithoutName(args.OriginalSource)
);
stackoutput.Children.Add(text);
(stackoutput.Parent
as ScrollViewer).ScrollToBottom();
}
String TypeWithoutName(
object obj)
{
string[] types = obj.GetType().ToString().Split('.');
return types[types.Length - 1];
}
}

当我们右键点击窗口的button文字区域:

 

看到顺序是:PreviewMouseDown-》MouseDown-》PreviewMouseUp-》MouseUp。

对于Preview类型的事件来说,他是从父节点往子节点传递,称之为下沉事件路由。

对于非Preview类型事件,我们可以看到,他是有事件触发的子节点往父节点传递,称之为冒泡事件路由。

我们鼠标右键点击事件发生后,首先整个窗口会收到鼠标点击的消息,然后通过碰撞检测,来一步步确定触发这个事件的子控件,所有Preview发生顺序为win->grid->button->textblock.

当所有的Preview完成后,程序会开始使用wpf内核的逻辑来处理这个事件发射机制,让这个事件以什么样的形式发送出去给各个控件,并且按照一个既定的顺序。

当我们右键点击窗口的button非文字区域:

 

除了触发点的不一样跟上面没有什么区别。

可以看到源控件是button, OriginalSource是buttonChrome。

发出事件的控件有:window-》grid-》button。buttonChrome是一个类,button使用它来绘制按钮界面。

 

上面都是使用右键点击,使用左键呢?

 

PreviewMouseDown事件的触发过程跟上面一样,但是MouseDown仅仅触发到TextBlock之后就不在触发。为什么呢?

查看源码中的buttonbase类,发现他重写了OnMouseLeftButtonDown,并将Handled设置为true.

 

View Code
protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
{
if (this.ClickMode != System.Windows.Controls.ClickMode.Hover)
{
//截断MouseDown的路由
e.Handled = true;
base.Focus();尝试将焦点设置在当前控件上(button)
if (e.ButtonState == MouseButtonState.Pressed)
{
base.CaptureMouse();//当前控件捕获鼠标事件,之后的鼠标事件将会直接将当前控件设置为OriginalSource。
if (base.IsMouseCaptured)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
if (!this.IsPressed)
{
this.SetIsPressed(true);
}
}
else
{
base.ReleaseMouseCapture();
}
}
}
base.OnMouseLeftButtonDown(e);
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
//由于在上面已经设置鼠标事件的接受控件为button,所以在鼠标左键up的时候触发这个事件的就是button。
if (this.ClickMode != System.Windows.Controls.ClickMode.Hover)
{
//设置事件不在路由上去。所有我们看到MouseUp事件没有出现。再触发的时候就已经做了处理
e.Handled = true;
bool flag = (!this.IsSpaceKeyDown && this.IsPressed) && (this.ClickMode == System.Windows.Controls.ClickMode.Release);
if (base.IsMouseCaptured && !this.IsSpaceKeyDown)
{
base.ReleaseMouseCapture();
}
if (flag)
{
//在此处触发OnClick
this.OnClick();
}
}
base.OnMouseLeftButtonUp(e);
}
//触发ClickEvent事件。
protected virtual void OnClick()
{
// ClickEvent事件。会路由上去。
RoutedEventArgs e = new RoutedEventArgs(ClickEvent, this);
base.RaiseEvent(e);
CommandHelpers.ExecuteCommandSource(
this);
}

在按钮获取焦点之后,点击键盘上的空格键:

 

对于前几个事件我们都能够理解,为什么后面出现了Click事件呢?原因是他重写了OnKeyDown

 

View Code
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
if (this.ClickMode != System.Windows.Controls.ClickMode.Hover)
{
if (e.Key == Key.Space)
{
if ((((Keyboard.Modifiers & (ModifierKeys.Control | ModifierKeys.Alt)) != ModifierKeys.Alt) && !base.IsMouseCaptured) && (e.OriginalSource == this))
{
this.IsSpaceKeyDown = true;
this.SetIsPressed(true);
base.CaptureMouse();
if (this.ClickMode == System.Windows.Controls.ClickMode.Press)
{
this.OnClick();//触发click事件。
}
e.Handled
= true;//禁止事件路由
}
}

我们尝试着自定义一个routeevent,看看这个事件是如何使用的。尝试模拟一下路由事件的产生和触发。我们在textblock中触发这个事件。

 

View Code
class KnockButton : Button
{
public static readonly RoutedEvent PreviewKnockEvent;
public static readonly RoutedEvent KnockEvent;

static KnockButton()
{
PreviewKnockEvent
= EventManager.RegisterRoutedEvent("PreviewKnock", RoutingStrategy.Tunnel, typeof(RoutedEventHandler), typeof(KnockButton));
KnockEvent
= EventManager.RegisterRoutedEvent("Knock", RoutingStrategy. Bubble, typeof(RoutedEventHandler), typeof(KnockButton));
}
public event RoutedEventHandler Knock
{
add {
this.AddHandler(KnockEvent, value); }
remove {
this.RemoveHandler(KnockEvent, value); }
}
public event RoutedEventHandler PreviewKnock
{
add {
this.AddHandler(PreviewKnockEvent, value); }
remove {
this.RemoveHandler(PreviewKnockEvent, value); }
}
}
class KnockWindow:Window
{
public static readonly RoutedEvent PreviewKnockEvent;
public static readonly RoutedEvent KnockEvent;
static KnockWindow()
{
PreviewKnockEvent
= KnockButton.PreviewKnockEvent.AddOwner(typeof(KnockWindow));
KnockEvent
= KnockButton.KnockEvent.AddOwner(typeof(KnockWindow));
}
public event RoutedEventHandler Knock
{
add {
this.AddHandler(KnockEvent, value); }
remove {
this.RemoveHandler(KnockEvent, value); }
}
public event RoutedEventHandler PreviewKnock
{
add {
this.AddHandler(PreviewKnockEvent, value); }
remove {
this.RemoveHandler(PreviewKnockEvent, value); }
}
}
class KnockGird:Grid
{
public static readonly RoutedEvent PreviewKnockEvent;
public static readonly RoutedEvent KnockEvent;
static KnockGird()
{
PreviewKnockEvent
= KnockButton.PreviewKnockEvent.AddOwner(typeof(KnockGird));
KnockEvent
= KnockButton.KnockEvent.AddOwner(typeof(KnockGird));
}
public event RoutedEventHandler Knock
{
add {
this.AddHandler(KnockEvent, value); }
remove {
this.RemoveHandler(KnockEvent, value); }
}
public event RoutedEventHandler PreviewKnock
{
add {
this.AddHandler(PreviewKnockEvent, value); }
remove {
this.RemoveHandler(PreviewKnockEvent, value); }
}
}
class KnockTextBlock : TextBlock
{
public static readonly RoutedEvent PreviewKnockEvent;
public static readonly RoutedEvent KnockEvent;
static KnockTextBlock()
{
PreviewKnockEvent
= KnockButton.PreviewKnockEvent.AddOwner(typeof(KnockTextBlock));
KnockEvent
= KnockButton.KnockEvent.AddOwner(typeof(KnockTextBlock));
}
public event RoutedEventHandler Knock
{
add {
this.AddHandler(KnockEvent, value); }
remove {
this.RemoveHandler(KnockEvent, value); }
}
public event RoutedEventHandler PreviewKnock
{
add {
this.AddHandler(PreviewKnockEvent, value); }
remove {
this.RemoveHandler(PreviewKnockEvent, value); }
}
protected override void OnMouseEnter(MouseEventArgs e)
{
//重写OnMouseEnter,当鼠标进入textblock区域,就会发出事件。
base.OnMouseEnter(e);
RoutedEventArgs args
= new RoutedEventArgs();
args.RoutedEvent
= PreviewKnockEvent;
args.Source
= this;
RaiseEvent(args);
args
= new RoutedEventArgs();
args.RoutedEvent
= KnockEvent;
args.Source
= this;
RaiseEvent(args);
}
}

将我们界面上原有的控件全部换成新的控件,然后鼠标进入,看看事件的触发顺序。

 

可以看到preview虽然是在KnockTextBlock中触发的,但是第一个获取到此事件的是KnockWindow,这是因为我们在定义这个事件的时候将事件的路由类型选择为RoutingStrategy.Tunnel。我们可以看到这个事件的路由跟我们预想的是一样的。同理Knock事件的发生顺序也是合理的。

如果我们将preview事件改为Direct会怎么样呢?

 

如图,这个事件将只会在触发这个事件的控件中发生,而不会在其他父控件中发生。

在这里我们肯定非常想知道这个事件是如何在这些控件中路由的。我们下面就手动写一个程序,来模拟wpf中的路由事件机制。

对于。Net中的事件我们知道他一般是这样定义的:

 

View Code
class NetEvent
{
//定义一个委托作为事件的处理器默认类型。
public delegate void Mydelegate();
//定义一个事件
public event Mydelegate ExmpleEvent;
//触发事件
public void MakeEvent()
{
//执行事件处理器
ExmpleEvent();
}
}
static void Main()
{
NetEvent netZ
= new NetEvent();
netZ.ExmpleEvent
+= new NetEvent.Mydelegate(netZ_ExmpleEvent);
netZ.MakeEvent();
}
static void netZ_ExmpleEvent()//事件处理器
{
Console.WriteLine(
"netZ_ExmpleEvent");
}

但是有一个问题,在wpf中,我们希望我们的事件的灵活性更大,而且在一个控件上触发输入操作的内核事件后,我们希望这个事件可以被所有在这个区域的控件都获取,让控件去选择是否处理自己感兴趣的事件。

比如说,你点击窗口上一个按钮,那你同时肯定也点击了窗口,以及容纳按钮的父控件,我们能让这里面所有在逻辑上都应该被触发的控件都获取到这个事件吗?可以。这就是路由事件的好处之一。

好处之二,所有的事件在处理的过程中可以有一定的顺序,我们可以按照这个顺序来选择在什么时候截断路由。

 

View Code 1
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace WpfRoutedEvent
{
public delegate void MyEventhandler(MyDependencyObject sender,MyRoutedEventArgs args);
public enum RoutingStrategy
{
Tunnel,
Bubble,
Direct
}

public class MyRoutedEvent
{
private int _globalIndex;
private Type _handlerType;
private string _name;
private Type _ownerType;
private RoutingStrategy _routingStrategy;
private bool _handld;

internal MyRoutedEvent(string name, RoutingStrategy routingStrategy, Type handlerType, Type ownerType)
{
this._name = name;
this._routingStrategy = routingStrategy;
this._handlerType = handlerType;
this._ownerType = ownerType;
this._handld = false;
this._globalIndex = MyGlobalEventManager.GetNextAvailableGlobalIndex(this);
}

public MyRoutedEvent AddOwner(Type ownerType)
{
MyGlobalEventManager.AddOwner(
this, ownerType);
return this;
}

public bool Handld
{
get { return this._handld; }
set { this._handld = value; }
}
internal int GlobalIndex
{
get
{
return this._globalIndex;
}
}

public Type HandlerType
{
get
{
return this._handlerType;
}
}

public string Name
{
get
{
return this._name;
}
}

public Type OwnerType
{
get
{
return this._ownerType;
}
}

public RoutingStrategy RoutingStrategy
{
get
{
return this._routingStrategy;
}
}
}

public static class MyGlobalEventManager
{
private static int _countRoutedEvents = 0;
/// <summary>
/// 储存所有的路由事件对应的处理器
/// 分布如下:首先按类分
/// 接着按照路由事件分
/// 接着按照处理器存储(一个类的路由事件可能有多个处理器)
/// </summary>
private static Hashtable classListenersLists = new Hashtable();
private static DependencyObjectType _dependencyObjectType = DependencyObjectType.FromSystemTypeRecursive(typeof(MyDependencyObject));
/// <summary>
/// 储存所有类的所有路由事件和类的对应关系。每个类一个键值对:键为DependencyObjectType,值为一个list,这个list中存储该类所有的MyRoutedEvent
/// </summary>
private static Hashtable _dTypedRoutedEventList = new Hashtable();
//存储所有的路由事件对象
private static ArrayList _globalIndexToEventMap = new ArrayList(100);
/// <summary>
/// 注册一个路由事件到容器中
/// </summary>
/// <param name="name"></param>
/// <param name="routingStrategy"></param>
/// <param name="handlerType"></param>
/// <param name="ownerType"></param>
/// <returns></returns>
internal static MyRoutedEvent RegisterRoutedEvent(string name, RoutingStrategy routingStrategy, Type handlerType, Type ownerType)
{
MyRoutedEvent routedEvent
= new MyRoutedEvent(name, routingStrategy, handlerType, ownerType);
_countRoutedEvents
++;
AddOwner(routedEvent, ownerType);
return routedEvent;
}
/// <summary>
/// 注册一个路由事件对应的事件处理器
/// </summary>
/// <param name="classType"></param>
/// <param name="routedEvent"></param>
/// <param name="handler"></param>
/// <param name="handledEventsToo"></param>
internal static void RegisterClassHandler(Type classType, MyRoutedEvent routedEvent, MyEventhandler handler, bool _handledEventsToo)
{
DependencyObjectType type
= DependencyObjectType.FromSystemTypeRecursive(classType);
List
<ClassHandlers> _eventHandlersList = (List<ClassHandlers>)classListenersLists[type];
//如果存在classType的路由事件列表
if (_eventHandlersList != null)
{
int index = -1;
List
<MyRoutedEventHandlerInfo> _RoutedEventHandlerInfoList;
for (int i = 0; i < _eventHandlersList.Count; i++)
{
//查找特定的路由事件在这个列表中是否存在
if (_eventHandlersList[i].RoutedEvent == routedEvent)
{
index
= i;
}
}
if (index !=-1)
{
//如果存在这个事件的的处理器列表,添加这个新的事件处理器到列表中
_RoutedEventHandlerInfoList = _eventHandlersList[index].HandlersList;
_RoutedEventHandlerInfoList.Add(
new MyRoutedEventHandlerInfo(handler, _handledEventsToo));
}
else
{
//不存在,则创建一个对应路由事件的节点,添加到类型列表中。
ClassHandlers item = new ClassHandlers();
//为item创建一个List<MyRoutedEventHandlerInfo>存储所有的路由处理器信息
item.HandlersList =new List<MyRoutedEventHandlerInfo>();
item.HandlersList.Add(
new MyRoutedEventHandlerInfo(handler, _handledEventsToo));
item.RoutedEvent
= routedEvent;
_eventHandlersList.Add(item);
}
}
else
{
//如果不存在对应类的列表
//先创建一个对应类的节点
_eventHandlersList = new List<ClassHandlers>();
//在新创建的类型节点中添加上当前事件及处理器列表
ClassHandlers item = new ClassHandlers();
item.HandlersList
=new List<MyRoutedEventHandlerInfo>();
item.HandlersList.Add(
new MyRoutedEventHandlerInfo(handler, _handledEventsToo));
item.RoutedEvent
= routedEvent;
_eventHandlersList.Add(item);
//将对应类的事件路由添加进去
classListenersLists.Add(type, _eventHandlersList);
}



}

internal static void ReMoveClassHandler(Type classType, MyRoutedEvent routedEvent, Delegate handler)
{
DependencyObjectType type
= DependencyObjectType.FromSystemTypeRecursive(classType);
List
<ClassHandlers> _eventHandlersList = (List<ClassHandlers>)classListenersLists[type];
//如果存在classType的路由事件列表
if (_eventHandlersList != null)
{
int index = -1;
List
<MyRoutedEventHandlerInfo> _RoutedEventHandlerInfoList;
for (int i = 0; i < _eventHandlersList.Count; i++)
{
//查找特定的路由事件在这个列表中是否存在
if (_eventHandlersList[i].RoutedEvent == routedEvent)
{
_RoutedEventHandlerInfoList
= _eventHandlersList[index].HandlersList;
for (int j = 0; j < _RoutedEventHandlerInfoList.Count;j++ )
{
if (_RoutedEventHandlerInfoList[i].Handler.Equals(handler))
{
_RoutedEventHandlerInfoList.RemoveAt(i);
}
}
}
}
}
}
/// <summary>
/// 添加一个路由事件对应的类
/// </summary>
/// <param name="routedEvent"></param>
/// <param name="ownerType"></param>
internal static void AddOwner( MyRoutedEvent routedEvent ,Type ownerType)
{
if ((ownerType != typeof(MyDependencyObject)) && !ownerType.IsSubclassOf(typeof(MyDependencyObject)))
{
List
<MyRoutedEvent> list2;
DependencyObjectType type
= DependencyObjectType.FromSystemTypeRecursive(ownerType);
object obj3 = _dTypedRoutedEventList[type];
if (obj3 == null)
{
list2
= new List<MyRoutedEvent>(1);
_dTypedRoutedEventList[type]
= list2;
}
else
{
list2
= (List<MyRoutedEvent>)obj3;
}
if (!list2.Contains(routedEvent))
{
list2.Add(routedEvent);
}
}
else
{
List
<MyRoutedEvent> list2;
object obj3 = _dTypedRoutedEventList[ownerType];
if (obj3 == null)
{
list2
= new List<MyRoutedEvent>(1);
_dTypedRoutedEventList[ownerType]
= list2;
}
else
{
list2
= (List<MyRoutedEvent>)obj3;
}
if (!list2.Contains(routedEvent))
{
list2.Add(routedEvent);
}
}

}
/// <summary>
/// 存储路由事件在一个aRRAYLIST中,返回这个事件的索引
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
internal static int GetNextAvailableGlobalIndex(object value)
{
return _globalIndexToEventMap.Add(value);
}
/// <summary>
/// 查找对应索引的事件
/// </summary>
/// <param name="globalIndex"></param>
/// <returns></returns>
internal static object EventFromGlobalIndex(int globalIndex)
{
return _globalIndexToEventMap[globalIndex];
}
/// <summary>
/// 查找具体事件
/// </summary>
/// <param name="name"></param>
/// <param name="ownerType"></param>
/// <returns></returns>
internal static MyRoutedEvent GetRoutedEventFromName(string name, Type ownerType)
{
if ((ownerType != typeof(MyDependencyObject)) && !ownerType.IsSubclassOf(typeof(MyDependencyObject)))
{
//对于非DependencyObject或者DependencyObject的子类,存储路由事件的时候KEY是Type
while (ownerType != null)
{
//DependencyObjectType type = DependencyObjectType.FromSystemTypeRecursive(ownerType);
List<MyRoutedEvent> list = (List<MyRoutedEvent>)_dTypedRoutedEventList[ownerType];
if (list != null)
{
for (int i = 0; i < list.Count; i++)
{
MyRoutedEvent event2
= list[i];
if (event2.Name.Equals(name))
{
return event2;
}
}
}
ownerType
= ownerType.BaseType;
}
}
else
{
//对于DependencyObject或者DependencyObject的子类,存储的Key是DependencyObjectType
for (DependencyObjectType type = DependencyObjectType.FromSystemTypeRecursive(ownerType); type != null; type = type.BaseType)
{
List
<MyRoutedEvent> list2 = (List<MyRoutedEvent>)_dTypedRoutedEventList[type];
if (list2 != null)
{
for (int j = 0; j < list2.Count; j++)
{
MyRoutedEvent event3
= list2[j];
if (event3.Name.Equals(name))
{
return event3;
}
}
}
}
}
return null;
}

internal static List<MyRoutedEventHandlerInfo> GetRoutedEventhandlerFromName(string name, Type ownerType)
{
DependencyObjectType type
= DependencyObjectType.FromSystemTypeRecursive(ownerType);
List
<ClassHandlers> _eventHandlersList = (List<ClassHandlers>)classListenersLists[type];
List
<MyRoutedEventHandlerInfo> _RoutedEventHandlerInfoList = null;
//如果存在classType的路由事件列表
if (_eventHandlersList != null)
{

for (int i = 0; i < _eventHandlersList.Count; i++)
{
//查找特定的路由事件在这个列表中是否存在
if (_eventHandlersList[i].RoutedEvent.Name.Equals(name))
{
_RoutedEventHandlerInfoList
= _eventHandlersList[i].HandlersList;
}
}
}
return _RoutedEventHandlerInfoList;
}
}
View Code 2
public class DependencyObjectType
{
private DependencyObjectType _baseDType;
private static int DTypeCount = 0;
private int _id;
private static Hashtable DTypeFromCLRType = new Hashtable();
public static DependencyObjectType FromSystemTypeRecursive(Type systemType)
{
DependencyObjectType type
= (DependencyObjectType)DTypeFromCLRType[systemType];
if (type == null)
{
type
= new DependencyObjectType();
DTypeFromCLRType[systemType]
= type;
if (systemType != typeof(MyDependencyObject))
{
//父类比子类的id要小,因为查找的时候首先建立的是子类的DependencyObjectType
//这是一个递归的构造过程。从最上层的DependencyObject类一直都当前类
type._baseDType = FromSystemTypeRecursive(systemType.BaseType);
}
type._id
= DTypeCount++;
}
return type;
}
public int Id
{
get
{
return this._id;
}
}
public DependencyObjectType BaseType
{
get
{
return this._baseDType;
}
}
}


public class MyDependencyObject
{

}
/// <summary>
/// 存储事件以及事件的处理器链表
/// </summary>
internal struct ClassHandlers
{
internal MyRoutedEvent RoutedEvent;
internal List<MyRoutedEventHandlerInfo> HandlersList;
//internal bool handledEventsToo;
}
/// <summary>
/// 路由事件的参数
/// </summary>
public class MyRoutedEventArgs
{
private object _originalSource;
private MyRoutedEvent _routedEvent;
private object _source;
private bool _handled;
public bool Handled
{
get
{
return this._handled;
}
set
{
this._handled = value;
}
}
public object Source
{
get
{
return this._source;
}
set
{
object source = value;
if (this._source != source)
{
this._source = source;
}
}
}
public MyRoutedEventArgs(MyRoutedEvent routedEvent, object source)
{
this._routedEvent = routedEvent;
this._source = this._originalSource = source;
this._handled = false;
}
public object OriginalSource
{
get
{
return this._originalSource;
}
}
public MyRoutedEvent RoutedEvent
{
get
{
return this._routedEvent;
}
set
{
this._routedEvent = value;
}
}
public MyRoutedEventArgs()
{
this._handled = false;
}

}

/// <summary>
/// 路由事件的委托以及这个委托是否可以在控件树种传递
/// </summary>
public struct MyRoutedEventHandlerInfo
{
private MyEventhandler _handler;
private bool _handledEventsToo;
internal MyRoutedEventHandlerInfo(MyEventhandler handler, bool handledEventsToo)
{
this._handler = handler;
this._handledEventsToo = handledEventsToo;
}

public Delegate Handler
{
get
{
return this._handler;
}
}
public bool Handled
{
get
{
return this._handledEventsToo;
}
}
internal void InvokeHandler(object target, MyRoutedEventArgs routedEventArgs)
{
if (!routedEventArgs.Handled || this._handledEventsToo)
{
(
this._handler)((MyDependencyObject)target, routedEventArgs);
}
}
}



/// <summary>
/// 存储EventRout对象的工程(栈)
/// </summary>
internal static class MyEventRouteFactory
{
private static MyEventRoute[] _eventRouteStack;
private static int _stackTop;
private static object _synchronized = new object();

internal static MyEventRoute FetchObject(MyRoutedEvent routedEvent)
{
MyEventRoute route
= Pop();
if (route == null)
{
return new MyEventRoute(routedEvent);
}
route.RoutedEvent
= routedEvent;
return route;
}

private static MyEventRoute Pop()
{
lock (_synchronized)
{
if (_stackTop > 0)
{
MyEventRoute route2
= _eventRouteStack[--_stackTop];
_eventRouteStack[_stackTop]
= null;
return route2;
}
}
return null;
}

private static void Push(MyEventRoute eventRoute)
{
lock (_synchronized)
{
if (_eventRouteStack == null)
{
_eventRouteStack
= new MyEventRoute[2];
_stackTop
= 0;
}
if (_stackTop < 2)
{
_eventRouteStack[_stackTop
++] = eventRoute;
}
}
}

}
public class MyEventRoute
{
private Stack<BranchNode> _branchNodeStack = new Stack<BranchNode>();
public MyRoutedEvent RoutedEvent;
public List<MyUielement> sernderList = new List<MyUielement>();
List
<Delegate> HandlersList = new List<Delegate>();
private struct BranchNode
{
public object Node;
public object Source;
}

public MyEventRoute(MyRoutedEvent routedEvent)
{
RoutedEvent
= routedEvent;
}

public List<Typehandlerinfo> Gethandlers()
{
List
<Typehandlerinfo> mainList = new List<Typehandlerinfo>();
for (int i = 0; i < sernderList.Count;i++ )
{
MyUielement obj
= sernderList[i];
mainList.Add(
new Typehandlerinfo(MyGlobalEventManager.GetRoutedEventhandlerFromName(RoutedEvent.Name, obj.GetType())));
}
return mainList;
}

public void AddSoures(MyUielement obj)
{
sernderList.Add(obj);
}
public struct Typehandlerinfo
{
public List<MyRoutedEventHandlerInfo> _eventHandlersList;
public Typehandlerinfo(List<MyRoutedEventHandlerInfo> _eventHandlersList)
{
this._eventHandlersList = _eventHandlersList;
}
}
}


}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WpfRoutedEvent
{
public class MyElement : MyDependencyObject
{
private MyElement _content;
public MyElement Content
{
set
{
this._content = value;
value._UIPrenat
= this;
}
}
private MyElement _UIPrenat = null;
public MyElement UIParent
{
get { return _UIPrenat; }
}
/// <summary>
/// 将一个事件以及其事件处理器添加到链表里面
/// </summary>
/// <param name="routedEvent"></param>
/// <param name="handler"></param>
public void AddHandler(MyRoutedEvent routedEvent, MyEventhandler handler, bool _handledEventsToo)
{
MyGlobalEventManager.RegisterClassHandler(
this.GetType(), routedEvent, handler, _handledEventsToo);
}
public void RemoveHandler(MyRoutedEvent routedEvent, Delegate handler)
{
MyGlobalEventManager.ReMoveClassHandler(
this.GetType(), routedEvent, handler);
}
public void RaiseEvent(MyRoutedEventArgs e)
{
MyEventRoute route
= MyEventRouteFactory.FetchObject(e.RoutedEvent);
if (e.RoutedEvent.RoutingStrategy == RoutingStrategy.Direct)
{
//直接处理
route.AddSoures(this);
foreach (MyRoutedEventHandlerInfo handler in route.Gethandlers()[0]._eventHandlersList)
{
handler.InvokeHandler(
this, e);
}
}
else
{
MyElement obj
= this;
while (obj != null)
{
route.AddSoures(obj);
obj
= obj._UIPrenat;
}
if (e.RoutedEvent.RoutingStrategy == RoutingStrategy.Bubble)
{
//冒泡
for (int i = 0; i < route.Gethandlers().Count; i++)
{
foreach (MyRoutedEventHandlerInfo handler in route.Gethandlers()[i]._eventHandlersList)
{
handler.InvokeHandler(route.sernderList[i], e);
if (handler.Handled || e.RoutedEvent.Handld)
{
return;
}
}
}
}
else
{
//隧道
for (int i = route.Gethandlers().Count - 1; i >= 0; i--)
{
foreach (MyRoutedEventHandlerInfo handler in route.Gethandlers()[i]._eventHandlersList)
{
handler.InvokeHandler(route.sernderList[i], e);
if (handler.Handled || e.RoutedEvent.Handld)
{
return;
}
}
}
}
}
route.Clear();
}
}
public class MyUielement : MyElement
{
public static readonly MyRoutedEvent PreviewTestEvent =
MyGlobalEventManager.RegisterRoutedEvent(
"PreviewTest",
RoutingStrategy.Tunnel,
typeof(MyEventhandler), typeof(MyUielement));

public static readonly MyRoutedEvent TestEvent =
MyGlobalEventManager.RegisterRoutedEvent(
"Test",
RoutingStrategy.Bubble,
typeof(MyEventhandler), typeof(MyUielement));
public event MyEventhandler PreviewTest
{
add{
this.AddHandler(PreviewTestEvent, value, false);}
remove{
this.RemoveHandler(PreviewTestEvent, value);}
}
public event MyEventhandler Test
{
add
{
this.AddHandler(TestEvent, value,false);
}
remove
{
this.RemoveHandler(TestEvent, value);
}
}

}
public class MyMianWin :MyElement
{
}
public class MyWin:MyUielement
{
}
public class MyGrid : MyUielement
{
}
public class Mybutton : MyUielement
{
}

}
View Code 3
class progrm
{
static void Main()
{
MyMianWin mainwin
= new MyMianWin();
MyWin win
= new MyWin();
MyGrid grid
= new MyGrid();
Mybutton btn
= new Mybutton();
mainwin.Content
= win;
win.Content
= grid;
grid.Content
= btn;
win.PreviewTest
+= Onevent1;
grid.PreviewTest
+= Onevent1;
btn.PreviewTest
+= Onevent1;
win.Test
+= Onevent1;
grid.Test
+= Onevent1;
btn.Test
+= Onevent1;
//mainwin并不包含这个事件的定义,但是他仍然能够处理这个事件。
mainwin.AddHandler(Mybutton.PreviewTestEvent, Onevent1, false);
mainwin.AddHandler(Mybutton.TestEvent, Onevent1,
false);
while (true)
{
Console.WriteLine(
"输入!B BUTTON G GRID W WIN 触发:");
string ch = Console.ReadLine();
switch (ch)
{
case "B":
MyRoutedEventArgs args
= new MyRoutedEventArgs(Mybutton.PreviewTestEvent, btn);

btn.RaiseEvent(args);
args
= new MyRoutedEventArgs(Mybutton.TestEvent, btn);

btn.RaiseEvent(args);
break;
case "G":
MyRoutedEventArgs args1
= new MyRoutedEventArgs(MyGrid.PreviewTestEvent, grid);

grid.RaiseEvent(args1);
args1
= new MyRoutedEventArgs(MyGrid.TestEvent, grid);

grid.RaiseEvent(args1);
break;
case "W":
MyRoutedEventArgs args2
= new MyRoutedEventArgs(MyWin.PreviewTestEvent, win);
win.RaiseEvent(args2);
args2
= new MyRoutedEventArgs(MyWin.TestEvent, win);
win.RaiseEvent(args2);
break;
}
}

}

static void Onevent1(MyDependencyObject sender, MyRoutedEventArgs args)
{
Console.WriteLine(sender.GetType().Name
+"------" + args.RoutedEvent.Name);
}
static void Onevent2(MyDependencyObject sender, MyRoutedEventArgs args)
{
args.Handled
= true;
}
}

以上程序详细的模拟了wpf中的路由事件的工作机制。