我有一个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 )之间以及.NET和JS在WebBrowser内部的互操作性的技术。
我可以用一个对象(标记为WebBrowser.ObjectForScripting )设置ComVisibleAttribute,对象将在JS中访问。
我甚至可以从嵌入式Silverlight应用程序中获得对这个对象的引用:
(ScriptObject) HtmlPage.Window.GetProperty("external");我还可以通过HtmlPage.RegisterScriptableObject(“名称”,anObject)使Silverlight应用程序中的一些对象对JS可见(可能还有宿主代码);
但。问题是,在所有情况下,我都必须处理一些非类型化的ScriptObject实例。但是我想在主机和SL应用程序之间建立“完全管理的代码”通信。我的意思是传递复杂的结构/类/委托、引发事件等等,即没有任何“非类型化的JS-东西”。
我怎么能这么做?
UPDATE:好的,似乎没有很好的方法来做我想做的事情。所以我要处理JS-互操作性问题。但在这里我有个问题。我在主机上设置了ObjectForScripting,而SL-app可以使用它。这意味着SL-app从在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对象的消息“方法或操作没有实现”。好吧,它不能被看作是动态的,但是它是什么呢?如何在它上调用任何方法?
发布于 2011-02-08 16:11:28
目前还没有管理的互操作。您提到的两个选项( DOM桥上的JavaScript互操作或COM托管)都是存在的。
我非常赞赏你所做的研究--当我点击这个问题时,你知道我要说的一切!
发布于 2011-02-08 15:53:06
我不完全确定您将如何在SL应用程序和主机之间传递复杂的结构,但是您在引发事件时可以使用的一个选项是通过URL传递信息。将事件处理程序附加到WebBroswer.Navigated事件,并让该处理程序根据url中的信息引发主机事件。
例如,我们有一个承载在WPF WebBrowser控件中的Silverlight应用程序。我们想知道用户何时点击Silverlight应用程序中的“关闭”按钮。我们将一个事件处理程序附加到WebBrowser.Navigated并解析了该URL。我们专门在那个网址中寻找"closed=true“。如果找到,关闭整个应用程序(包括WPF主机)。
https://stackoverflow.com/questions/4934935
复制相似问题