Monday, March 19, 2007

WPF/E - How to get the id of the hosting WPF/E control

UPDATE - 05.06.2007 - The content of this post is no longer valid with the 1.0 beta release of Silverlight.

The February 2007 CTP of the WPF/E SDK provides the "GetHost" method which enables ANY UIElement to get the hosting WPF/E control of the object. Unfortunately, there is not a property or method that exposes the ID of the WPF/E control (as of the Feb 2007 CTP). In the event you are attempting to create a reusable component, you will probably want the ID of the control so that you can reuse all of the JavaScript you have laboriously authored :)

After reviewing the items available through the WPF/E control API, I settled on an approach that seems usable. I used the SourceElement property when I declared my WPF/E control. Click the button below to display the WPF/E control information.

The key item to notice is that these are two seperate instances of the same xaml file. The source code for this implementation is available at the end of this post.

I simply declared the WPF/E control in the HTML as follows:

<div id="wpfeControl1Host">
  <script type="text/javascript">
    new agHost
      "wpfeControl1Host", // hostElementID (HTML element to put WPF/E control into)
      "wpfeControl1", // ID of the WPF/E ActiveX control we create
      "400", // Width
      "400", // Height
      "white", // Background color
      "wpfeControl1", // SourceElement (name of script tag containing xaml)
      "plugin.xaml", // Source file
      "false", // IsWindowless
      "30", // MaxFrameRate
      null // OnError handler

Notice the relationship between the "ID of the WPF/E ActiveX control", the "SourceElement" property, and the
id of the containing "Div" element. The relationships are as follows:
  • The "SourceElement" is set to the ID of the WPF/E ActiveXControl
  • The "hostElementID" is set to the "SourceElement" + a unique number to identify the instance
  • The "id" of the "div" tag is set to the "hostElementID". I point this out simply because if you are using this as a checklist you can just go down the list.
This naming structure is implemented to give us the flexibility of obtaining BOTH the id of the WPF/E ActiveX control and the id of the hosting element from the JavaScript. Now that we have setup the relationships we can obtain the various

Using the "WPF/E JavaScript Application" Visual Studio 2005 Template asa basis, simply replace the "handleMouseUp" function
with the following:

function handleMouseUp(sender, eventArgs)
  var gradientStop1 = sender.findName("gradientStop1");
  var gradientStop2 = sender.findName("gradientStop2");
  gradientStop1.offset = 1;
  gradientStop2.offset = .403;

  // Obtain a reference to the WPF/E control
  var wpfeControl = sender.GetHost();
  var displayString = new String();

  // Display the ID of the ActiveX (WPF/E) control
  displayString += "The ID of the ActiveXControl is " + wpfeControl.SourceElement + "\n\n";

  // Display the ID of the HTML element that is hosting the control
  var hostingElementID = wpfeControl.SourceElement + "Host";
  displayString += "The ID of the Hosting HTML element is " +   hostingElementID + "\n\n";

  // Display the HTML of the "control" for the sake of proof
  if (document.all)
    var hostingElement = document.getElementById(hostingElementID);
    displayString += "The HTML of the \"control\"\n";
    displayString += "-------------------------------------------";
    displayString += hostingElement.outerHTML;

I settled upon this approach primarily because it worked :). However, I was originally led down the path because of the comment in the HTML file that states "// SourceElement (name of script tag containing xaml)". I think the confusion is because of there seems to be a discrepency between this comment and the contents of the information within the SDK for the "SourceElement" property. I look forward to your comments.

Project Information
    Source Code: here
    Requirements: WPF/E February 2007 CTP


Bryant Likes said...

The source element property is for using xaml that is embedded in a script tag. It is ignore if you set the source file property (so that works in this case). But it is actually useful when you want to just put the xaml right in the page itself instead of having a seperate file.

Mike Harsh said...

This is a great post Chad. You're not the first person to have this request. :) We've got a work item to add the id of the hosting control to the object returned by the getHost() method. We'll e adding this to WPF/E soon.