I am working on making a very simple IFrame control for silverlight.
Goal: Control the placement of an IFrame overlayed on a silverlight application
The silverlight IFrame control is being used inside a silverlight application that allows the user to build a search query, then a url is formed from the search query and set to be the source of the IFrame. It's a basic search application.
I want the IFrame to change size and position based on the size and position of the silverlight control.
I found code here: http://www.kirupa.com/blend_silverlight/absolute_position_transformtovisual.htm, that I put in the constructor of the silverlight control to get the position of the control relative to the silverlight application. I then use that position to set the IFrameLeft and IFrameTop dependency properties of the silverlight control.
this.LayoutUpdated += (obj, args) =>
{
GeneralTransform gt = HtmlViewerStackPanel.TransformToVisual(null);
Point point = gt.Transform(new Point());
IFrameLeft = (int)point.X;
IFrameTop = (int)point.Y;
};
Then in the SizeChanged event I have the following which makes the changes to the IFrame. In the constructor I set FrameID to be a new Guid. Then create an IFrame with that Guid as the id.
private void UserControl_SizeChanged(object sender, SizeChangedEventArgs e)
{
IFrameHeight = (int)this.ActualHeight;
IFrameWidth = (int)this.ActualWidth;
var iframeElement = System.Windows.Browser.HtmlPage.Document.GetElementById(this.IFrameID);
iframeElement.SetStyleAttribute("width", string.Format("{0}px", IFrameWidth));
iframeElement.SetStyleAttribute("height", string.Format("{0}px", IFrameHeight));
}
It only works as desired if the silverlight application takes up the whole browser window. However that is not how I most commonly use it.
From reading this question: Getting absolute position of an element relative to browser, it appears that if I could get a reference to the object tag HtmlElement that the silverlight application is hosted in I could read the offsetleft and offsettop properties. If I had the position of the object tag relative to the browser it seems like I could very easily calculate the silverlight control's offset from the browser. Since I can determine the silverlight control's offset from the silverlight application.
In the past I have just given the object, or a wrapping div tag an id and then used the HtmlPage.Document.GetElementById to get a reference to the element. I'd like to avoid that if possible.
I tried this in the LayoutUpdated event after getting the GeneralTransform and setting the IFrame Left and Top. It gets the object tag and uses the offset properties I talked about before.
var objectElements = System.Windows.Browser.HtmlPage.Document.GetElementsByTagName("object");
if (objectElements.Count == 1)
{
var objElement = objectElements.Single();
do
{
IFrameLeft += Convert.ToInt32(objElement.GetProperty("offsetLeft"));
IFrameTop += Convert.ToInt32(objElement.GetProperty("offsetTop"));
} while ((objElement=(System.Windows.Browser.ScriptObject)objElement.GetProperty("offsetParent")) != null);
}
Using the object tag to get the offset from the browser window works, I was having some problems with one of the pages I tested it on then I learned that the offsets are from offsetparent instead of always from the browser window. I added the code to loop untill the offsetparent is null. The code now basicly works.
I want to be able to put the silverlight control anywhere, and the IFrame be contained to the area of the control, and be at the position of the control.
I'm wide open to any ideas on a better approach to positioning the IFrame to match the silverlight control.
Here are a few more examples of what I'm trying to do:
- http://www.wintellect.com/cs/blogs/jlikness/archive/2010/09/19/hosting-html-in-silverlight-not-out-of-browser.aspx
- http://www.davidezordan.net/blog/?p=700
- http://csharp-snippets.blogspot.com/2009/03/html-host-control-in-silverlight.html
- http://www.codeproject.com/KB/silverlight/BlendPDFwithSilverlight.aspx