public void TestPropagateEvent()
        {
            // create a hierarchy of UIElements
            //               (00)
            //                | 
            //               (10)
            //             /     \
            //          (20)      (21)
            //            |       /  \
            //          (30)    (31)  (32)
            var element00 = new ContentControlTest();
            var element10 = new StackPanel();
            var element20 = new ContentControlTest();
            var element21 = new StackPanel();
            var element30 = new UIElementLayeringTests();
            var element31 = new UIElementLayeringTests();
            var element32 = new UIElementLayeringTests();
            element00.Content = element10;
            element10.Children.Add(element20);
            element10.Children.Add(element21);
            element20.Content = element30;
            element21.Children.Add(element31);
            element21.Children.Add(element32);
            var elements = new List<UIElement> { element00, element10, element20, element21, element30, element31, element32 };

            // create routed events
            var tunnelingEvent = EventManager.RegisterRoutedEvent<RoutedEventArgs>("TestTuneling", RoutingStrategy.Tunnel, typeof(UIElementLayeringTests));
            var bubblingEvent = EventManager.RegisterRoutedEvent<RoutedEventArgs>("TestBubbling", RoutingStrategy.Bubble, typeof(UIElementLayeringTests));
            var directEvent = EventManager.RegisterRoutedEvent<RoutedEventArgs>("TestDirect", RoutingStrategy.Direct, typeof(UIElementLayeringTests));

            // test propagation direction, propagation bounds and sender values
            foreach (var uiElement in elements)
            {
                uiElement.AddHandler(tunnelingEvent, TestAddSenderToList);
                uiElement.AddHandler(bubblingEvent, TestAddSenderToList);
                uiElement.AddHandler(directEvent, TestAddSenderToList);
            }

            // tunneling test 1
            senderList.Clear();
            element20.RaiseEvent(new RoutedEventArgs(tunnelingEvent));
            Assert.AreEqual(3, senderList.Count);
            Assert.AreEqual(element00, senderList[0]);
            Assert.AreEqual(element10, senderList[1]);
            Assert.AreEqual(element20, senderList[2]);

            // tunneling test 2
            senderList.Clear();
            element31.RaiseEvent(new RoutedEventArgs(tunnelingEvent));
            Assert.AreEqual(4, senderList.Count);
            Assert.AreEqual(element00, senderList[0]);
            Assert.AreEqual(element10, senderList[1]);
            Assert.AreEqual(element21, senderList[2]);
            Assert.AreEqual(element31, senderList[3]);

            // direct test
            senderList.Clear();
            element10.RaiseEvent(new RoutedEventArgs(directEvent));
            Assert.AreEqual(1, senderList.Count);
            Assert.AreEqual(element10, senderList[0]);

            // tunneling test 1
            senderList.Clear();
            element30.RaiseEvent(new RoutedEventArgs(bubblingEvent));
            Assert.AreEqual(4, senderList.Count);
            Assert.AreEqual(element30, senderList[0]);
            Assert.AreEqual(element20, senderList[1]);
            Assert.AreEqual(element10, senderList[2]);
            Assert.AreEqual(element00, senderList[3]);

            // tunneling test 2
            senderList.Clear();
            element20.RaiseEvent(new RoutedEventArgs(bubblingEvent));
            Assert.AreEqual(3, senderList.Count);
            Assert.AreEqual(element20, senderList[0]);
            Assert.AreEqual(element10, senderList[1]);
            Assert.AreEqual(element00, senderList[2]);

            // test with another type of handler
            var eventMyTestHandler = EventManager.RegisterRoutedEvent<MyTestRoutedEventArgs>("TestMyTestHandler", RoutingStrategy.Direct, typeof(UIElementLayeringTests));
            AddHandler(eventMyTestHandler, TestMyTestHandler);
            RaiseEvent(new MyTestRoutedEventArgs(eventMyTestHandler));
            Assert.AreEqual(true, testMyTestHandlerCalled);

            // test Handled and EventHandledToo
            foreach (var uiElement in elements)
            {
                uiElement.RemoveHandler(bubblingEvent, TestAddSenderToList);
                uiElement.AddHandler(bubblingEvent, TestHandledHandler);
            }
            senderList.Clear();
            element00.AddHandler(bubblingEvent, TestEventHandledHandler, true);
            element32.RaiseEvent(new RoutedEventArgs(bubblingEvent));
            Assert.AreEqual(1, senderList.Count);
            Assert.AreEqual(element32, senderList[0]);
            Assert.AreEqual(true, testEventHandledTooCalled);

            // test class handlers basic working
            foreach (var uiElement in elements)
                uiElement.RemoveHandler(bubblingEvent, TestHandledHandler);
            EventManager.RegisterClassHandler(typeof(ContentControl), bubblingEvent, TestAddSenderToClassHandlerList);
            element30.RaiseEvent(new RoutedEventArgs(bubblingEvent));
            Assert.AreEqual(2, classHandlerSenderList.Count);
            Assert.AreEqual(element20, classHandlerSenderList[0]);
            Assert.AreEqual(element00, classHandlerSenderList[1]);

            // test that class handlers are called before instance handlers + test handledEventToo for class handlers
            senderList.Clear();
            classHandlerSenderList.Clear();
            EventManager.RegisterClassHandler(typeof(ContentControl), bubblingEvent, TestClassHandlerHandled);
            EventManager.RegisterClassHandler(typeof(StackPanel), bubblingEvent, TestClassHandlerEventHandled, true);
            foreach (var uiElement in elements)
                uiElement.AddHandler(bubblingEvent, TestAddSenderToList);
            element20.RaiseEvent(new RoutedEventArgs(bubblingEvent));
            Assert.AreEqual(1, classHandlerSenderList.Count);
            Assert.AreEqual(element20, classHandlerSenderList[0]);
            Assert.AreEqual(0, senderList.Count);
            Assert.AreEqual(true, testClassHandlerEventHandledTooCalled);
        }