Silverlight angepasst (Teil 2)
Kommentare

using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

namespace SilverlightWebExample
{
public class WebBrowser : ContentControl
{
public string

using System;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;

namespace SilverlightWebExample
{
    public class WebBrowser : ContentControl
    {
        public string Source { get; set; }

        public WebBrowser()
        {
            Loaded += WebBrowser_Loaded;
        }

        private void WebBrowser_Loaded(object sender, RoutedEventArgs e)
        {
            if(string.IsNullOrEmpty(Source))
                return;

            Navigate(new Uri(Source));
        }

        public void Navigate(Uri uri)
        {
            Source = uri.ToString();

            HtmlDocument document = HtmlPage.Document;

            HtmlElement divElement = GetDivElement(document);
            HtmlElement iframeElement = GetIframeElement(document);

            divElement.AppendChild(iframeElement);
            document.Body.AppendChild(divElement);
        }

        public void NavigateToString(string text)
        {
            Point currentPosition = GetCurrentPosition();
            HtmlDocument document = HtmlPage.Document;

            HtmlElement divElement = GetDivElement(document);
            divElement.SetStyleAttribute("left", currentPosition.X + "px");
            divElement.SetStyleAttribute("top", currentPosition.Y + "px");
            divElement.SetProperty("innerhtml", text);

            document.Body.AppendChild(divElement);
        }

        private HtmlElement GetDivElement(HtmlDocument document)
        {
            HtmlElement divElement = document.CreateElement("div");
            divElement.SetStyleAttribute("position", "absolute");
            divElement.SetAttribute("id", Guid.NewGuid().ToString());
            divElement.SetStyleAttribute("height", Height + "px");
            divElement.SetStyleAttribute("width", Width + "px");
            divElement.SetStyleAttribute("left", "0px");
            divElement.SetStyleAttribute("top", "0px");
            divElement.SetStyleAttribute("z-index", "0px");

            return divElement;
        }

        private HtmlElement GetIframeElement(HtmlDocument document)
        {
            Point currentPosition = GetCurrentPosition();

            HtmlElement iframeElement = document.CreateElement("IFRAME");
            iframeElement.SetAttribute("src", Source);
            iframeElement.SetStyleAttribute("height", Height + "px");
            iframeElement.SetStyleAttribute("width", Width + "px");
            iframeElement.SetStyleAttribute("left", currentPosition.X + "px");
            iframeElement.SetStyleAttribute("position", "relative" );
            iframeElement.SetStyleAttribute("top", currentPosition.Y + "px");
            iframeElement.Id = Guid.NewGuid().ToString();
            
            return iframeElement;
        }

        private Point GetCurrentPosition()
        {
            UpdateLayout();
            return TransformToVisual(Application.Current.RootVisual).Transform(new Point(0,0));
        }
    }
}  

Die Methode NavigateToString unterscheidet sich nun darin, dass beliebiger HTML-Code im DIV-Element angezeigt werden soll. Hierbei wird dem DIV-Element-Objekt nur noch die Position des XAML-Controls mitgegeben. Der manuelle HTML-Code wird dann dem DIV-Element-Objekt mittels SetProperty und innerhtml vergeben.

In Listing 2 fällt aber noch ein weiterer Punkt auf, der Konstruktor, der das Loaded-Event abonniert hat. Die Methode zum Loaded-Event überprüft nur, ob bereits eine URL der Property Source vergeben wurde. Wenn ja, wird die Navigate-Methode aufgerufen, andernfalls wird die Methode mit return sofort verlassen. Doch für welchen Zweck wurde dieser Punkt hinzugefügt? Ganz einfach, wenn Silverlight die XAML-Oberfläche aufbaut, wird von jedem XAML-Control eine Instanz erzeugt. Nun soll ja automatisch, wenn ein URL dem Control zugewiesen wurde, dieser URL aufgerufen und dargestellt werden. Aus diesem Grund wurde der Konstruktor verwendet. Das Loaded-Event stellt in diesem Fall nur sicher, dass es erst weitergeht, wenn die Oberfläche bereits gezeichnet wurde. Denn wurde die Oberfläche noch nicht gezeichnet, kann die Position des XAML-Controls nicht mehr ermittelt werden und es gibt eine Exception.


  
        
            
            
            
        
      
        
  
  

Um das neue WebBrowser-Steuerelement einsetzen zu können, muss es der Oberfläche noch als XAML hinzugefügt werden (Listing 3). Nun gibt es unterschiedliche Möglichkeiten, das WebBrowser-Steuerelement zu verwenden. Sie sind mit dem in Silverlight 4 folgenden WebBrowser Control vergleichbar und in Listing 4 und 5 demonstriert. Das Ergebnis im Browser ist in Abbildung 4 zu sehen.

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    void MainPage_Loaded( object sender, RoutedEventArgs e )
    {
        HtmlContent.Navigate(new Uri("http://www.dotnet-blog.net"));
    }
}  
public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
        Loaded += MainPage_Loaded;
    }

    void MainPage_Loaded( object sender, RoutedEventArgs e )
    {
        HtmlContent.NavigateToString( "
Gregor Biswanger
" ); } }
Webinhalt innerhalb einer Silverlight-Anwendung darstellen
Webinhalt innerhalb einer Silverlight-Anwendung darstellen

Nun dürfte aber beim Testen noch ein Fehler aufgefallen sein, nämlich, dass beim Klicken im Silverlight-Bereich das WebBrowser Control wieder verschwindet. Das liegt daran, dass die Silverlight-Anwendung im Browser immer auf höchster Ebene nach vorne gerendert wird. Der HTML-DOM-Bereich ist ja ein eigenständiger Bereich des Browsers und wird somit in den Hintergrund gebracht. Um das zu verhindern, muss dem Silverlight-Plug-in über einen Parameter mitgeteilt werden, dass nur einzelne Elemente der Silverlight-Anwendung explizit gezeichnet werden sollen und nicht der gesamten Oberfläche im Browser. Schlussendlich bedeutet das, dass Windowless angibt, ob das Silverlight-Plug-in als fensterloses Plug-in angezeigt wird, oder legt dieses fest. Dazu fügt man der HTML oder ASPX-Seite, den Parameter windowless mit dem Value-Wert true (Listing 6).

  

Gregor Biswanger ist Consultant bei der Firma TRIA IT-solutions in München. Seine Schwerpunkte liegen im Bereich der .NET-Architektur und agilen Prozessen. Biswanger ist außerdem freier Autor, Trainer, Speaker und Microsoft CLIPler der INdotNET (Ingolstädter .NET Developers Group). Sie erreichen seinen Blog unter www.dotnet-blog.net.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -