Sunday, May 1, 2011

Using TransformToVisual in Silverlight to position HTML elements.

I'm in the process of developing a Silverlight custom control that "hosts" a Flash instance. The way that you do this, of course, is to position the HTML element in question over your Silverlight instance, as described, say, here. The problem I'm running into is that when I use the GeneralTransform.Transform() method to get the absolute coordinates of my control, so that I can position the HTML element correctly, the Point object that's returned always has .X=0 and .Y=0.

public void InitControl(string id)
    GeneralTransform gt = this.TransformToVisual(Application.Current.RootVisual);
    Point localPos = gt.Transform(new Point(_htmlControlLeft, _htmlControlTop));

    // Create the containing DIV tag.
    HtmlDocument doc = HtmlPage.Document;
    divHost = doc.CreateElement("div");
    divHost.SetAttribute("id", System.Guid.NewGuid().ToString());
    divHost.SetStyleAttribute("position", "absolute");
    divHost.SetStyleAttribute("left", localPos.X.ToString() + "px"); // always 0
    divHost.SetStyleAttribute("top", localPos.Y.ToString() + "px"); // always 0
    Debug.WriteLine("x,y=" + localPos.X.ToString() + "," + localPos.Y.ToString());
    divHost.SetStyleAttribute("width", Width.ToString() + "px");
    divHost.SetStyleAttribute("height", Height.ToString() + "px");
    divHost.SetStyleAttribute("z-index", _htmlZIndex.ToString());

I haven't been able to find great documentation on the GeneralTransform.Transform() method, but it seems like I'm using it correctly. Any thoughts on what I'm doing wrong?

Edit 4/28/09: I still haven't found an answer, but I AM using the Transform() method properly. The problem only shows up if I call the InitControl() method during the Page.Loaded event. If I wait a few seconds, then call it (say) from a Button_Click event, the same code works fine. According to the SL docs, everything should be laid out appropriately by the time the Page.Loaded event fires, but clearly that's not the case.

I should also note that every once in a while, the code above works perfectly fine, even when it's called from the Page.Loaded event. Huh.

My workaround so far, for what it's worth, is hide the control for a couple seconds after the form loads, then show it. It's an ugly hack, but unless anyone has any better ideas...?

From stackoverflow
  • This is due to RootVisual having a 0,0 x/y axis. Try using the next element within the tree, typically it's layoutRoot by default (assuming you haven't changed its name etc). That or utilise FindName() to ensure you have a direct reference to the said layer you are wanting to position the iFrame over.

    Scott Barnes / Rich Platforms Product Manager / Microsoft.

    Ken Smith : Thanks, Scott. BTW, if MS could possibly (please, please, please) get webcam support into SL 3.0, this nasty bit of SL -> JS -> Flash interaction wouldn't be necessary. Anything you can do for us on that?
    Scott Barnes : Its definately one our feature req list. We're in SL4 planning at the moment, so i'll make sure it gets echoed loud and clear! :)


Post a Comment