Welcome to MSDN Blogs Sign in | Join | Help

CLR Event vs. Routed Event: Two Demo Applications

As you may have already known, you can define and use Dependency Property as well as CLR Property in Avalon. (If you want to know more about Avalon’s property system, stay tuned in this blog.) Same thing can be said about CLR Event and Routed Event. By supporting routed event in Avalon, the parent element can participate in events sourcing from its child elements. This blog post presents two applications to show the differences between CLR event and RoutedEvent.

 

The first application is a Windows Form 2.0 application. WinForm only uses CLR event. System.Windows.Forms.Control.MouseMove event, for example, occurs when the mouse pointer is moved over the control. That control can choose to handle it by registering an event handler. But if it does not handle it, its parent control will not be notified that MouseMove event occurs for one of its child controls.

 

Compile the complete WinForm code below into a WinExe application and run it. Event handler outerPanel_MouseMove prints out the timestamp for each MouseMove event received by outerPanel(Green area). As you can see, when the mouse is moved into innerPanel (Blue area), event handler is not called. That makes sense for CLR event since the event now occurs for innerPanel instead of outerPanel.

 

Of course, to respond to MouseMove on innerPanel as well, you can hook up event handler on innerPanel itself. You do not need to do that in Avalon with Routed Event, though.

 

using System;

using System.Collections.Generic;

using System.Windows.Forms;

 

namespace ZhanboBlog.Demo

{

  static class Program

  {

    [STAThread]

    static void Main()

    {

      Application.EnableVisualStyles();

      Application.Run(new DemoForm());

    }

  }

 

  internal class DemoForm : Form

  {

    internal DemoForm()

    {

      InitializeComponent();

    }

 

    private void InitializeComponent()

    {

      this.Text = "Zhanbo Blog Demo 01";

      this.Width = 600;

      this.Height = 600;

 

      info = new Label();

      info.Text = "Blog Demo";

      info.Font = new System.Drawing.Font("Arial", 20);

      info.Dock = DockStyle.Top;

      info.AutoEllipsis = true;

      info.Height = 50;

 

      outerPanel = new Panel();

      outerPanel.BackColor = System.Drawing.Color.Green;

      outerPanel.MouseMove += new MouseEventHandler(outerPanel_MouseMove);

      outerPanel.Dock = DockStyle.Fill;

 

      innerPanel = new Panel();

      innerPanel.Width = 100;

      innerPanel.Height = 100;

      innerPanel.Left = 50;

      innerPanel.Top = 100;

      innerPanel.BackColor = System.Drawing.Color.Blue;

 

      this.Controls.Add(info);

      this.Controls.Add(outerPanel);

      this.outerPanel.Controls.Add(innerPanel);

    }

 

    void outerPanel_MouseMove(object sender, MouseEventArgs e)

    {

      System.Text.StringBuilder sb = new System.Text.StringBuilder();

      sb.Append("MouseMove at ");

      sb.Append(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff tt"));

 

      info.Text = sb.ToString();

    }

 

    private Label info;

    private Panel outerPanel;

    private Panel innerPanel;

  }

}

 

In Avalon, MouseMove is a Routed Event. To be exact, it is a RoutedEvent with Bubble routing strategy. It means that MouseMove event moves up from source element to root element. In the previous demo, if RoutedEvent were used, event handler would still be called even if mouse is moving into innerPanel (Blue area). That is what you are seeing in the Avalon application below.

 

Create an Avalon application, edit Window1.xaml to be:

 

<Window x:Class="AvalonApplication1.Window1"

    xmlns="http://schemas.microsoft.com/winfx/avalon/2005"

    xmlns:x="http://schemas.microsoft.com/winfx/xaml/2005"

    Text="Zhanbo Blog Demo 01"

    Width="600"

    Height="600">

    <DockPanel>

        <TextBlock x:ID="info"

                   TextContent="Blog Demo"

                   FontFamily="Arial"

                   FontSize="20"

                   DockPanel.Dock="Top"/>

        <Canvas x:ID="outerCanvas"

                Width="200"

                Height="200" 

                Background="Green"

                MouseMove="CanvasMouseMove"

                DockPanel.Dock="Top"

                >

            <Canvas x:ID="innerCanvas" Width="100" Height="100"

                    Canvas.Top="50" Canvas.Left="50"

                    Background="Blue" />

        </Canvas>

    </DockPanel>

</Window>

 

In the code behind, add the event handler as follows:

void CanvasMouseMove(object sender, System.Windows.Input.MouseEventArgs e)

{

    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    sb.Append("MouseMove at ");

    sb.Append(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff tt"));
    info.TextContent = sb.ToString();

}

 

Please note that MouseEventArgs defined by WinForm and Avalon are under different namespaces and with different APIs.

 

By running this application, you can clearly see that outerCanvas receives MouseMove event when it occurs directly on itself and indirectly on its child control, which is innerCanvas. We can differentiate these two scenarios by checking MouseEventArgsSource property. Simply speaking, Source property refers to the object that raised the event. In the above demo application, Source can be either outerCanvas or innerCanvas. Let’s put it into use by changing the event handler in code behind:

 

void CanvasMouseMove(object sender, System.Windows.Input.MouseEventArgs e)

{

    System.Text.StringBuilder sb = new System.Text.StringBuilder();

    sb.Append("MouseMove at ");

sb.Append(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss:ffff tt"));

    if (e.Source == innerCanvas)

    {

        sb.Append(" within inner canvas");

    }

    else

    {

        sb.Append(" within canvas");

    }

info.TextContent = sb.ToString();

}

 

I end this post with a question for my reader. If you want to reset info text back to initial string (Zhanbo Blog Demo 01) when the mouse left canvas area (i.e. when there is no MouseMove event to handle), I should handle a different event MouseLeave on outerCanvas. Let’s edit the XAML to add the attribute:

        <Canvas x:ID="outerCanvas"

                Width="200"

                Height="200" 

                Background="Green"

                MouseMove="CanvasMouseMove"

                MouseLeave="CanvasMouseLeave"

                DockPanel.Dock="Top"

                >

Now, what to add inside this new event handler? The shorter, the better. Of course, it has to be correct first.

void CanvasMouseLeave(object sender, MouseEventArgs e)

{

    //Question for my reader

}

 

(This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm)

Published Saturday, April 02, 2005 4:10 AM by zhanbos
Filed under:

Comments

Saturday, April 02, 2005 6:10 AM by Zhanbo Sun [MS]

# CLR Event vs. Routed Event: Two Demo Applications

Because it is extremely difficult to paste code snippet into longhornblogs' new rich text editor, I have...
Wednesday, November 15, 2006 2:07 AM by WPF Team Bloggers

# CLR Event vs. Routed Event: Two Demo Applications

Because it is extremely difficult to paste code snippet into longhornblogs' new rich text editor, I have

Sunday, November 25, 2007 5:58 PM by Feed Search Engine - All Fresh Articles And News Are Here

# Feed Search Engine - All Fresh Articles And News Are Here

# Realize NET Potential CLR Event vs Routed Event Two Demo Applications | Indoor Grills

Anonymous comments are disabled
 
Page view tracker