• Silverlight 4 WebBrowser的使用及调用 WebBrowser 中的 javascript 方法


    下面是MSDN的使用说明:

    The following example shows how to handle the ScriptNotify event. In this example, the InvokeScript is called, which in turn calls the LoadSearch function in the following HTML. 
    The HTML file must be hosted in the same domain as the Silverlight application. The Javascript within the HTML page calls window.external.notify,
     which raises the ScriptNotify event in the Silverlight application
    必须在同一个域下才可用哦!

    example:


        The following example shows how to handle the ScriptNotify event. In this example, the InvokeScript is called, which in turn calls the LoadSearch function in the following HTML. The HTML file must be hosted in the same domain as the Silverlight application. The Javascript within the HTML page calls window.external.notify, which raises the ScriptNotify event in the Silverlight application.

    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head>
    <title></title>
    <script type="text/javascript" >
    function LoadSearch(searchString) {
    window.location
    = "http://www.bing.com/search?q=" + searchString
    window.external.notify(
    "Search completed")
    }
    </script>
    </head>
    <body>
    Silverlight WebBrowser control.
    </body>
    </html>

    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    }

    void WB1_ScriptNotify(object sender, NotifyEventArgs e)
    {
    Button1.Content
    = e.Value;
    Button1.IsEnabled
    = false;

    }

    private void Button1_Click(object sender, RoutedEventArgs e)
    {
    object results = WB1.InvokeScript("LoadSearch", new string[] { "Silverlight" });
    }
    }
    XAML

    <StackPanel x:Name="LayoutRoot" Height="358" Width="489" Background="LightBlue">
    <WebBrowser x:Name="WB1" Source="http://localhost/HTMLPage1.htm" Height="272" Width="379"
    ScriptNotify
    ="WB1_ScriptNotify" Margin="5" />
    <Button Width="200" x:Name="Button1" Content="Click to search!" Click="Button1_Click" />
    </StackPanel>

    详细实例请看下文(是一个外国家伙写的,很简单一看就懂的,不翻译了):

    Until version 4, Silverlight does not really have a mechanism for displaying HTML based content.

    Prior to version 4, you can have Silverlight controls and HTML UI co-existing in the browser and they can interoperate with each other in a rich way. You can even use transparency and windowless techniques to overlay them but you can’t really ask a Silverlight application to display HTML for you. You always have to get it done elsewhere and, furthermore, if you then packaged your application to run as a Silverlight Out-Of-Browser (SLOOB) app then those techniques wouldn’t help as you lose the ability to display HTML at all.

    That changes with version 4 with the new WebBrowser control ( WPF also has a Frame and a WebBrowser control which both offer levels of HTML hosting ability – the Silverlight WebBrowser looks like a subset of the WPF version ).

    The first thing to say about the WebBrowser control is that it only functions in Silverlight Out-Of-Browser applications ( SLOOBs ) – in the browser the control displays a blank UI so an application developer/designer would need to think about how that would work if the application can also be run within a browser window.

    For an out-of-browser application, I can put a simple UI together;

    <UserControl x:Class="SilverlightApplication16.MainPage"
    xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable
    ="d"
    d:DesignHeight
    ="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition />
    </Grid.RowDefinitions>
    <Grid
    x:Name
    ="gridControls">
    <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition
    Width
    ="Auto" />
    </Grid.ColumnDefinitions>
    <TextBox
    x:Name
    ="txtUri"
    Margin
    ="5"
    HorizontalAlignment
    ="Stretch" />
    <Button
    x:Name
    ="buttonGo"
    Grid.Column
    ="1"
    Content
    ="Go"
    Click
    ="OnGo"
    Margin
    ="5" />
    </Grid>
    <WebBrowser
    LoadCompleted
    ="BrowserLoadCompleted"
    Grid.Row
    ="1"
    Margin
    ="5"
    x:Name
    ="browserControl" />
    </Grid>
    </UserControl>

    and then add a little code-behind that;

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace SilverlightApplication16
    {
    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    }
    private void OnGo(object sender, RoutedEventArgs e)
    {
    buttonGo.IsEnabled
    = false;

    browserControl.Navigate(
    new Uri(txtUri.Text, UriKind.Absolute));
    }
    private void BrowserLoadCompleted(object sender, EventArgs e)
    {
    buttonGo.IsEnabled
    = true;
    }
    }
    }

    and ( out of browser ) that allows me to navigate to some HTML;

    image

    What might not be immediately obvious is that myPage.htm is part of the same web-site that the application originally came from ( i.e. site-of-origin ) and that an attempt to navigate to any site might fail ( subject to cross-domain policy ).

    That can be circumvented by having the application also elevate itself. If the application is elevated then cross-domain policy isn’t applied and so we can go anywhere as in the example below ( the application now having been installed as anelevated SLOOB );

    image

    You might notice that in this example this is me with my out-of-browser application visiting Microsoft.com which is made up of HTML and Silverlight. So…we have one Silverlight application hosting HTML which hosts another Silverlight application. Similarly, I can visit sites that have “other plugins” like the Flash site below;

    image

    I’m not sure how much/little this control is integrated into the Silverlight rendering engine. I tried ( for fun ) applying aPlaneProjection to it and that didn’t really work out so I’m not sure that you’re meant to use the control in this way ( more on doing fancy things with HTML without trying to bend the control in a moment but back to regular stuff for a second… )

    What you can also get the control to do is load HTML at runtime via its “NavigateToString” method so if I just change my code;

    private void OnGo(object sender, RoutedEventArgs e)
    {
    buttonGo.IsEnabled
    = false;

    browserControl.NavigateToString(txtUri.Text);
    }
    then I can just type HTML straight into the textbox and that works out fine ( note – the application does not have to be elevated for this to work );

    image

    Now, in the WPF version of this control there are two other “interesting” functions on the control. One is called InvokeScriptand that exists on the Silverlight control and can be used to invoke a piece of script inside the control.

    This isn’t intended to work if you use the Navigate method but there’s another way to set the URL which is the Sourceproperty and so I can re-jig my code a little bit such that the code-behind looks like;

    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    }
    private void OnGo(object sender, RoutedEventArgs e)
    {
    buttonGo.IsEnabled
    = false;
    browserControl.Source
    = new Uri(txtUri.Text, UriKind.Absolute);
    }
    private void BrowserLoadCompleted(object sender, EventArgs e)
    {
    browserControl.InvokeScript(
    "ChangeText", "Done");
    buttonGo.IsEnabled
    = true;
    }
    }
    and if I then edit the HTML that I want to load so it looks like;
    <html>
    <head>
    <script type="text/javascript">
    function ChangeText(text) {
    document.getElementById(
    "myDiv").innerText = text;
    }
    </script>
    </head>
    <body>
    <div id="myDiv">Hello World</div>
    </body>
    </html>
    then when I load up that particular HTML file with the WebBrowser control I get the expected response straight away;

    image

    and so the Silverlight control loads the HTML and then runs the script which changes the DOM inside of the HTML. Note that this isn’t possible for cross-domain content.

    It’s also possible to communicate “back” from the hosted Javascript to the Silverlight control although it’s not as functional as it is in WPF. If I re-work my HTML code to look like;

    <html>
    <head>
    <script type="text/javascript">
    function buttonClick()
    {
    window.external.Notify(
    "They clicked!");
    }
    </script>
    </head>
    <body>
    <input type="button" value="test" onclick="buttonClick()" />
    </body>
    </html>
    and then change my Silverlight UI a little to add a new textbox;
    View Code
    <UserControl x:Class="SilverlightApplication16.MainPage"
    xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable
    ="d"
    d:DesignHeight
    ="300" d:DesignWidth="400">

    <Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
    <RowDefinition
    Height
    ="Auto" />
    <RowDefinition />
    </Grid.RowDefinitions>
    <Grid
    x:Name
    ="gridControls">
    <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition
    Width
    ="Auto" />
    </Grid.ColumnDefinitions>
    <TextBox
    x:Name
    ="txtUri"
    Margin
    ="5"
    HorizontalAlignment
    ="Stretch" />
    <Button
    x:Name
    ="buttonGo"
    Grid.Column
    ="1"
    Content
    ="Go"
    Click
    ="OnGo"
    Margin
    ="5" />
    </Grid>
    <TextBlock
    x:Name
    ="txtStatus"
    Margin
    ="5"
    Text
    ="Not set"
    Grid.Row
    ="1" />
    <WebBrowser
    LoadCompleted
    ="BrowserLoadCompleted"
    Grid.Row
    ="2"
    Margin
    ="5"
    x:Name
    ="browserControl"
    ScriptNotify
    ="OnScriptNotify">
    </WebBrowser>
    </Grid>
    </UserControl>

    with code-behind;

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace SilverlightApplication16
    {
    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();
    }
    private void OnGo(object sender, RoutedEventArgs e)
    {
    buttonGo.IsEnabled
    = false;
    browserControl.Source
    = new Uri(txtUri.Text, UriKind.Absolute);
    }
    private void BrowserLoadCompleted(object sender, EventArgs e)
    {
    buttonGo.IsEnabled
    = true;
    }
    private void OnScriptNotify(object sender, NotifyEventArgs e)
    {
    txtStatus.Text
    = e.Value;
    }
    }
    }

    then that allows the hosted Javascript to communicate through the WebBrowser control via the call towindow.external.Notify() which gets picked up on the .NET side by the ScriptNotify event on the WebBrowser control and I just handle it in a little handler and change the text on my txtStatus TextBlock to represent whatever was passed from Javascript ( this is running out-of-browser but not elevated ).

    The other “interesting” aspect of the HTML support is that Silverlight 4 also has an HTMLBrush which can take HTML content and paint areas so, whilst my previous attempt to integrated the WebBrowser control with the PlaneProjection system didn’t work very well, I can paint arbitrary areas with a brush. So, if I’ve got a little UI;

    View Code
    <UserControl
    x:Class
    ="SilverlightApplication18.MainPage"
    xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc
    ="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable
    ="d"
    d:DesignHeight
    ="300"
    d:DesignWidth
    ="400">

    <Grid
    x:Name
    ="LayoutRoot"
    Background
    ="White">
    <Grid.ColumnDefinitions>
    <ColumnDefinition />
    <ColumnDefinition />
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition
    Height
    ="Auto" />
    </Grid.RowDefinitions>
    <WebBrowser
    x:Name
    ="myBrowser"
    Grid.RowSpan
    ="2" />
    <Rectangle
    Grid.Column
    ="1"
    Margin
    ="10"
    RadiusX
    ="10"
    RadiusY
    ="10">
    <Rectangle.Fill>
    <HtmlBrush
    x:Name
    ="myBrush"
    SourceName
    ="myBrowser"
    Stretch
    ="Fill"/>
    </Rectangle.Fill>
    </Rectangle>
    <Button
    Grid.Column
    ="1"
    Content
    ="Redraw"
    Grid.Row
    ="1"
    Margin
    ="5"
    Click
    ="OnRedraw" />
    </Grid>
    </UserControl>

    with some code behind it ( note – I feel I should be able to set the WebBrowser.Source property from XAML but it’s not working for me at the time of writing );

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;

    namespace SilverlightApplication18
    {
    public partial class MainPage : UserControl
    {
    public MainPage()
    {
    InitializeComponent();

    this.Loaded += (s, e) =>
    {
    myBrowser.Source
    = new Uri("http://www.microsoft.com", UriKind.Absolute);
    };
    }
    private void OnRedraw(object sender, RoutedEventArgs e)
    {
    myBrush.Redraw();
    }
    }
    }
    then that gives me a UI where I’m painting the rectangle on the right hand side with that HtmlBrush pointing to theWebBrowser control on the left hand side;

    image

    Note – this isn’t a VisualBrush and so it doesn’t do “live updates”. You’ll notice the Redraw button and the call toHtmlBrush.Redraw and that’s the mechanism for keeping things in sync so it’s more like a snapshot than anything else but pretty interesting regardless.

    激情燃烧
  • 相关阅读:
    BestCoder Round #65 hdu5590(水题)
    codeforces Ebony and Ivory(水题)
    codeforces 630B Moore's Law
    BestCoder Round #69 (div.2)(hdu5611)
    BestCoder Round #73 (div.2)(hdu 5630)
    codeforces 630A Again Twenty Five!
    codeforces 630C Lucky Numbers
    codeforces 630D Hexagons!
    Codeforces243C-Colorado Potato Beetle(离散化+bfs)
    hdu4453-Looploop(伸展树)
  • 原文地址:https://www.cnblogs.com/waren168/p/2064743.html
Copyright © 2020-2023  润新知