Een iframe in Silverlight

Deze week stond weer in het teken van Teezir Webcare:
- mooier uiterlijk;
- betere interactie met de stroom van real-time berichten via Facebook, Twitter en de meer dan 1200 bronnen die we crawlen;
- enkele nieuwe functionaliteiten, zoals het tonen van Twitter gebruiker informatie.

De eerste versie van Webcare bevatte nog lang niet alles wat een klant nodig heeft om real-time de informatie te volgen over zichzelf en haar producten. Hierdoor kwam het nog wel eens voor dat er andere programma’s, zoals Tweetdeck, nodig waren om te communiceren met de sociale media. In deze vernieuwde versie van Webcare zit dat allemaal wel en zijn de andere programma’s overbodig geworden.

Daarnaast wilden we de klant echt het gevoel geven dat alles binnen onze tool kan. Zelfs wanneer de link wordt geopend naar het originele online bericht, moet de klant het gevoel houden binnen Webcare te werken. Dit doel is eenvoudig te bereiken door een iframe te gebruiken waar de pagina in wordt geopend. Silverlight ondersteunt alleen standaard iframes voor desktop applicaties, maar niet voor web applicaties. Na veel speurwerk en wat voorbeeld code zijn we gekomen tot een Silverlight Control dat een iFrame laat zien in Webcare. Het control maakt een html iframe aan en toont deze bovenop de Silverlight applicatie. Wanneer de appliatie wordt verkleind of vergroot, schaalt het iframe gewoon mee.

<teezir:HtmlPlaceHolder Name="HtmlPlaceHolder1" SourceUrl="http://teezir.com"; />

///

/// Update the iframe location. Make it match the dimensions of this control.
///

private void UpdateLocation()
{
if (this.iFrame != null)
{
// Control position in window
GeneralTransform gt = this.TransformToVisual(Application.Current.RootVisual as UIElement);
Point offset = gt.Transform(new Point(0, 0));

// Placeholder top, left, with and height
int placeholderTop = (int)Math.Floor(offset.Y);
int placeholderLeft = (int)Math.Floor(offset.X);
int placeholderWidth = (int)Math.Floor(this.ActualWidth);
int placeholderHeight = (int)Math.Floor(this.ActualHeight);

// Adjust with padding of 10 pixels when the iframe is full size
int windowHeight = (int)Math.Floor(Application.Current.RootVisual.RenderSize.Height);
int windowWidth = (int)Math.Floor(Application.Current.RootVisual.RenderSize.Width);
if (placeholderWidth >= windowWidth)
{
placeholderLeft = 5;
placeholderWidth = windowWidth - 10;
}
if (placeholderHeight >= windowHeight)
{
placeholderTop = 5;
placeholderHeight = windowHeight - 10;
}

// Update iframe style
this.iFrame.SetStyleAttribute("width", placeholderWidth.ToString() + "px");
this.iFrame.SetStyleAttribute("height", placeholderHeight.ToString() + "px");
this.iFrame.SetStyleAttribute("left", placeholderLeft.ToString() + "px");
this.iFrame.SetStyleAttribute("top", placeholderTop.ToString() + "px");
}
}

 

Hierna kwam de echte uitdaging: het tonen van een iframe in een ChildWindow. In dat geval opent Silverlight een popup scherm met daarin het iframe. Ideaal voor het weergeven van een externe html pagina. Het popup scherm is te verplaatsen, maar standaard schuift het iframe dan niet mee. Om dit mogelijk te maken, moet er eerst worden uitgevonden of het iframe in een ChildWindow wordt getoond:

///

/// When the control is loaded, bind some events for updating the iframe.
///

private void HtmlPlaceHolder_Loaded(object sender, RoutedEventArgs e)
{
// Bind events to control
this.SizeChanged += HtmlPlaceHolder_SizeChanged;
this.LayoutUpdated += HtmlPlaceHolder_LayoutUpdated;

// Check if this control is in a child window
FrameworkElement parent = this as FrameworkElement;
while (parent != null)
{
// Close iFrame on close of the child window
Popup popup = parent as Popup;
if (popup != null)
{
popup.Closed += HtmlPlaceHolder_Closed;
windowed = true;
}

...

parent = parent.Parent as FrameworkElement;
}

// Update layout
UpdateLocation();
}

Vervolgens wordt bij het verplaatsen van de popup de locatie van het iframe bijgewerkt.

// Is this the child window?
if (VisualTreeHelper.GetChildrenCount(parent) > 0)
{
FrameworkElement contentroot = VisualTreeHelper.GetChild(parent, 0) as FrameworkElement;
if (contentroot != null)
{
contentroot.GotFocus += new RoutedEventHandler(HtmlPlaceHolder_GotFocus);
contentroot.SizeChanged += HtmlPlaceHolder_SizeChanged;
contentroot.LayoutUpdated += HtmlPlaceHolder_LayoutUpdated;

// Brute force, may be in the future some more
contentroot.MouseMove += new MouseEventHandler(HtmlPlaceHolder_MouseMove);
}
}

Wanneer de popup wordt getoond of gesloten wordt het iframe ook gesloten. Omdat het iframe een html frame is dat over de silverlight applicatie heen valt, is het gebruik van meerdere iframes over elkaar heen niet erg mooi. Maar in ons geval is dat niet erg, omdat dit niet kan voorkomen.

Helaas is het iframe niet gebruikt in webcare en zijn we toch voor een html popup scherm gegaan, omdat bepaalde sites een iframe popout script gebruiken, waardoor de browser naar de site wordt gestuurd en de gebruiker wordt uitgelogd van Webcare. De uiteindelijke versie in Webcare ziet er zo uit.

 

 

.

Wilt u meer informatie?