无缝地将 HTML 融入 Silverlight 页面






4.42/5 (7投票s)
本文将通过 .NET/JavaScript 互操作和 HTML 框架,展示一种将 HTML 页面无缝融入 Silverlight 页面的技术。
引言
本文解决的场景如下:我正在开发一个简单的图片查看器页面,顶部左侧有一个菜单。该菜单使用 Silverlight 开发。通过点击菜单按钮,用户可以在主页面上查看可调整大小的图片。除了显示图片,我还希望主页面能够显示 HTML 内容。此外,我希望使用 Silverlight 控件来显示图片或 HTML 内容。
需要解决两个问题
- 目前没有现成的 HTML Silverlight 控件可以渲染 HTML 页面。
- 如何将
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['']
GetMainFrame()
parent.GetMainFrame()
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 控件的布局并不容易。
历史
- 初始版本。