2011-02-08 56 views
1

我有一个WPF应用程序。我需要在其中嵌入Silverlight应用程序。据我所知最常见的做法是使用System.Windows.Controls.WebBrowser控件(注意:我的应用程序是wpf而不是WinForms)。
顺便说一句:还有另一种方法来托管Silverlight应用程序 - 使用其COM接口(请参阅http://www.codeproject.com/KB/atl/Host_Silverlight_In_ATL.aspx)。.NET桌面应用程序内嵌的Silverlight应用程序和它们之间的通信

所以在我的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之间的互操作性的技术。
我可以用一个对象(用ComVisibleAttribute标记)设置WebBrowser.ObjectForScripting并且该对象将在JS中访问。
我甚至可以从我的嵌入式Silverlight应用程序获得参考这个对象:

(ScriptObject) HtmlPage.Window.GetProperty("external"); 

我也可以让Silverlight应用程序到JS可见(可能举办的代码)通过HtmlPage.RegisterScriptableObject里面的一些对象(“名“, 一个东西);

但是。问题是,在所有情况下,我必须处理一些无类型的ScriptObject实例。 但我想在主机和SL-app之间建立“完全托管的代码”通信。我的意思是传递复杂的结构/类/代表,提高事件等等,即没有任何“无类型的JS东西”。

我该怎么做?

UPDATE: 好吧,似乎没有好方法来做我想做的事。 所以我必须处理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对象。好吧,它不能被视为动态的,但它是什么?如何调用它的任何方法?

回答

2

有没有在这个时间管理,只有互操作。您提到的两个选项(DOM桥接上的JavaScript互操作,或COM托管)都是存在的。

我赞扬你做你的研究 - 当我点击这个问题时,你知道我要说的一切!

0

我不完全确定如何在SL应用程序和主机之间传递复杂的结构,但是您可能在提高事件时选择的一个选项是通过URL传递信息。将事件处理程序附加到WebBroswer.Navigated事件,并让该处理程序根据url中的信息提升主机的事件。

例如,我们有一个托管在WPF WebBrowser控件内的Silverlight应用程序。我们想知道用户何时点击Silverlight应用程序中的“关闭”按钮。我们附加了一个事件处理程序到WebBrowser.Navigated并解析了URL。我们特别在该网址中查找“closed = true”。如果找到,关闭整个应用程序(包括WPF主机)。

Silverlight App inside WPF WebBrowser ?

+0

谢谢,这很好,但我需要主机和SL应用程序之间的沟通。 – Shrike 2011-02-08 15:56:31

相关问题