【发布时间】:2011-02-08 15:27:50
【问题描述】:
我有一个 WPF 应用程序。我需要在其中嵌入一个 Silverlight 应用程序。据我了解,最常见的方法是使用 System.Windows.Controls.WebBrowser 控件(注意:我的应用是 wpf 而不是 WinForms)。
顺便说一句:还有另一种方式来托管 Silverlight 应用程序 - 使用它的 COM 接口(请参阅http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx)。
所以在我的 WPF 应用程序中,我在某处有一个 WebBrowser:
<WebBrowser x:Name="webBrowser">
我在哪里加载我的 html 页面(为简单起见,我们假设本地 htlm 页面):
private void Window_Loaded(object sender, RoutedEventArgs e)
{
webBrowser.LoadCompleted += WebBrowser_LoadCompleted;
webBrowser.Navigate(new Uri(Path.GetFullPath("HostPage.htm")));
}
private void WebBrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
MessageBox.Show("Silverlight app has loaded");
}
好的。这很容易。
现在我想从 SL 应用程序与主机通信,并从主机与 SL 应用程序通信。
我了解 HTML(JS) 和 Silverlight (http://msdn.microsoft.com/en-us/library/cc645076%28VS.95%29.aspx) 之间以及 WebBrowser 中的 .NET 和 JS 之间的互操作性技术。
我可以使用一个对象(用 ComVisibleAttribute 标记)设置 WebBrowser.ObjectForScripting,并且该对象将在 JS 中访问。
我什至可以从我的嵌入式 Silverlight 应用程序中获得对这个对象的引用:
(ScriptObject) HtmlPage.Window.GetProperty("external");
我还可以通过 HtmlPage.RegisterScriptableObject("name", anObject); 使 Silverlight 应用程序中的某些对象对 JS(并且可能对宿主代码)可见。
但是。问题是在所有情况下我都必须处理一些无类型的 ScriptObject 实例。 但我想在主机和 SL 应用程序之间建立“完全托管的代码”通信。我的意思是传递复杂的结构/类/委托、引发事件等,即没有任何“无类型的 JS 材料”。
我该怎么做?
更新: 好的,似乎没有什么好方法可以做我想做的事。 所以我必须处理 JS 互操作性。但是在这里我有一个问题。 从我设置 ObjectForScripting 的主机上,SL-app 可以使用它。这意味着 SL 应用程序从 WebBrowser.ObjectForScripting 中设置的对象的方法中获取结果:
((ScriptObject) HtmlPage.Window.GetProperty("external")).Invoke("methodName")
但并非相反。 在我的 SL 应用程序中,我注册了一个对象(BridgeSl 类型):
m_bridgeSl = new BridgeSl();
HtmlPage.RegisterScriptableObject("bridge", m_bridgeSl);
然后在 html 中创建 JS 函数:
<script type="text/javascript">
var g_bridgeSl = null;
function pluginLoaded(sender, args) {
g_bridgeSl = sender.getHost().Content.bridge;
}
</script>
其中 pluginLoaded 是 SL 插件的 onLoad 事件的处理程序:
<object id="slCtrl" data="data:application/x-silverlight-2," type="application/x-silverlight-2" ...>
<param name="onLoad" value="pluginLoaded" />
</object>
然后添加返回这个对象的函数:
function getBridge() {
return g_bridgeSl;
}
我做了所有这些事情,因为我希望我可以在我的宿主应用程序中获取 BridgeSl 的实例:
var bridgeSl = WebBrowser.InvokeScript("getBridge");
其实我得到了一些东西。它是“System.__ComObject”的一个实例。但是当我将其转换为动态时:
dynamic dynBridgeSl = bridgeSl;
我得到带有消息“方法或操作未实现”的 System.SystemException 对象。好的,它不能被视为动态的,但那是什么?如何调用它的任何方法?
【问题讨论】:
标签: .net wpf silverlight interop