65.9K
CodeProject 正在变化。 阅读更多。
Home

无缝地将 HTML 融入 Silverlight 页面

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.42/5 (7投票s)

2009 年 2 月 8 日

CPOL

4分钟阅读

viewsIcon

63739

downloadIcon

1430

本文将通过 .NET/JavaScript 互操作和 HTML 框架,展示一种将 HTML 页面无缝融入 Silverlight 页面的技术。

引言

本文解决的场景如下:我正在开发一个简单的图片查看器页面,顶部左侧有一个菜单。该菜单使用 Silverlight 开发。通过点击菜单按钮,用户可以在主页面上查看可调整大小的图片。除了显示图片,我还希望主页面能够显示 HTML 内容。此外,我希望使用 Silverlight 控件来显示图片或 HTML 内容。

需要解决两个问题

  1. 目前没有现成的 HTML Silverlight 控件可以渲染 HTML 页面。
  2. 如何将 OnClick 事件从 Menu 控件路由到 Image 控件。

在接下来的章节中,我将展示解决上述问题的一个思路。

我假设读者熟悉 ASP.NET/C#、Silverlight、Visual Studio、JavaScript 和 DHTML。

背景

从 .NET 调用 JavaScript 函数

可以通过 System.Windows.Browser 命名空间中的 HtmlPage.Window.Invoke(name, param object[] args) 函数来实现从 .NET 代码调用 JavaScript 函数。

从 C# 函数 CallFooFromCSharp() 调用 JavaScript 函数 Foo() 的示例

C#/Silverlight 代码

using System.Windows.Browser;

class FooClass
{
    public void CallFooFromCSharp()
    {
        HtmlPage.Window.Invoke("Foo", "Hello World");
    }
}

JavaScript 代码

<script type="text/javascript">
function Foo(text) {
    alert(text);
}
</script>

从 JavaScript 调用 .NET/Silverlight 函数

与从 .NET 调用 JavaScript 函数相反的操作,可以通过先获取 Silverlight 对象,然后使用object.Content.[ObjectName].[FunctionName] 来调用函数。

从 JavaScript 函数 CallFooFromJavascript() 调用 C# 函数 Foo() 的示例

C#/Silverlight 代码

using System.Windows.Browser;

class FooClass
{
    [ScriptableMember]
    public void Foo()
    {
        // do something
    }
}

JavaScript 代码

<script type="text/javascript">
function CallFooFromJavascript() {
    var svlObject = document.getElementById("silverlightControl");
    svlObject.Content.FooClass.Foo();
}
</script>

使用 HTML FrameSet

在使用 FrameSet 时,我们需要了解的一个重要知识是如何

  • 获取框架对象
  • var parentFrame = parent.frames['']
  • 从父框架调用 JavaScript 函数 GetMainFrame()
  • parent.GetMainFrame()
  • 在一个框架的函数中调用另一个框架的 JavaScript 函数
  • var mainFrame = parent.GetMainFrame();
    mainFrame.Foo();

代码亮点

HtmlSilverlightBlend.zip 附件包含三个项目:ImageBrowser、MyMenu 和 SilverlightInterFrameCommunication.Web。

  • ImageBrowser 项目包含一个 ImageBrowser Silverlight 控件。
  • MyMenu 项目包含一个 MyMenu Silverlight 控件。
  • SilverlightInterFrameCommunication.Web 包含一个测试 Web 项目,其中 index.html 是定义 FrameSet 的根页面。

以下是处理 Silverlight 菜单按钮点击并路由到 JavaScript 函数 openImage()openPage() 的代码片段。

要显示一个显示特定图片的 Silverlight 控件,将调用 openImage() 函数并指定图片 URL。思路是,我们将调用一个 ASPX 页面,并将图片 URL 作为 'tag' 查询字符串传递。可以通过调用 HtmlPage.Document.QueryString["tag"] 从 Silverlight 控件访问查询字符串。

例如,我可以传递以下内容来告知 ImageBrowser 控件加载标签为 'A' 的图片:ImageBrowser.aspx?tag=<A>

openPage() 函数将打开一个 URL。这取决于 URL 的值以及该 URL 中提供的内容,但关键在于,您可以通过这种方法加载一个普通的 HTML 页面。

MyMenu.Xaml.cs

private void Button_Click(object sender, RoutedEventArgs e)
{
    Button sourceBtn = (Button)sender;

   switch (sourceBtn.Name)
    {
        case "Obama":
            HtmlPage.Window.Invoke("openImage", "ImageBrowser.aspx", "obama");
            break;
        case "Gates":
            HtmlPage.Window.Invoke("openImage", "ImageBrowser.aspx", "gates");
            break;
        ...
        case "Microsoft":
            HtmlPage.Window.Invoke("openPage", "http://www.microsoft.com");
            break;
        case "Google":
            HtmlPage.Window.Invoke("openPage", "http://www.google.com");
            break;
    }
}

MyMenu.aspx

function openImage(url, tag) {
    var imageUrl = url + "?tag=" + tag;

    // open imageUrl at mainFrame
    parent.OpenPage(imageUrl);
    parent.SetFooterCaption("My name is " + tag);
}

function openPage(url) {
    // open url at mainFrame
    parent.OpenPage(url);
    parent.SetFooterCaption("I am browsing " + url);
}

关注点

在 Silverlight.net 论坛上,已经报告了一种不同的技术/讨论,用于将 HTML 页面融入带有 Silverlight 控件的页面。论坛中提到的一种 hacky 的方法是使用 Silverlight 控件的 Opacity 属性(见下文)。

"Silverlight 不支持托管 HTML(不像 WPF 的 Frame 元素),但这不应该是障碍。还有另一种方法可以实现这一点。您可以使用 DIV 直接在 Silverlight 表面下方定位您的 HTML 内容。然后,将 Silverlight 插件(OBJECT 标签)声明为透明,并对 Silverlight 元素设置 IsHitTestVisible="false"。透明度将确保 HTML 内容得以显示。您可以在 Silverlight 中使用具有不透明颜色的元素等。这没问题。然后,命中测试可见性属性确保鼠标和键盘事件会穿过 Silverlight 进入下方的 HTML 表面。"

- Ashish Shetty | Program Manager | Microsoft

在本文中,我们展示了一种不同的解决 HTML 内容与 Silverlight 内容融合问题的方法,即使用 .NET/JavaScript 互操作和 HTML FrameSet

阅读本文后,读者应该对 .NET/JavaScript 互操作的工作方式更加熟悉,并学会一种将事件从一个 Silverlight 控件路由到另一个 Silverlight 控件的技术。该示例还展示了如何将查询字符串传递给 Silverlight 控件并进行处理。

非常感谢您的反馈/评论。如果您有不同的实现方法,例如,一种不使用 FrameSet 的单页面方法,请告诉我,我很想学习您的方法。我之所以采用这种方法,是因为我尝试过在 ASPX 页面中使用多个 Silverlight 控件的方法,并且发现使用 div/table 来处理多个 Silverlight 控件的布局并不容易。

历史

  • 初始版本。
© . All rights reserved.