我有一个WPF应用程序。我需要在其中嵌入一个Silverlight应用程序。据我所知,最常见的方法是使用System.Windows.Controls.WebBrowser控件(注意:我的应用程序是wpf而不是WinForms)。
BTW:还有另一种托管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-app和主机的SL-app与主机进行通信。
我理解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)在JS(也可能是托管代码)中看到Silverlight应用程序中的一些对象;
但是。问题是在所有情况下我都要处理一些无类型的ScriptObject实例。 但我想在主机和SL-app之间建立“完全托管代码”通信。我的意思是传递复杂的结构/类/委托,引发事件等,即没有任何“无类型的JS-stuff”。
我该怎么做?
更新: 好吧,似乎没有什么好方法可以做我想要的。 所以我必须处理JS互操作性。但在这里我有一个问题。 从主机我设置ObjectForScripting和SL-app可以使用它。这意味着SL-app从WebBrowser.ObjectForScripting中设置对象的方法获得结果:
((ScriptObject) HtmlPage.Window.GetProperty("external")).Invoke("methodName")
但不是相反。 在我的SL-app中,我注册了一个对象(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对象,并显示消息“方法或操作未实现”。好吧,它不能被视为动态,但那又是什么呢?如何调用它上面的任何方法?
答案 0 :(得分:2)
目前还没有托管互操作。您提到的两个选项(DOM桥接器上的JavaScript互操作或COM托管)都存在。
我确实赞扬你做研究 - 当我点击这个问题时,你知道我要说的一切!
答案 1 :(得分:0)
我不完全确定如何在SL应用程序和主机之间传递复杂的结构,但是在引发事件时可能有一个选项是通过URL传递信息。将事件处理程序附加到WebBroswer.Navigated
事件,并让该处理程序根据URL中的信息引发主机事件。
例如,我们有一个Silverlight应用程序,它托管在WPF WebBrowser控件中。我们想知道用户何时单击Silverlight应用程序中的“关闭”按钮。我们将事件处理程序附加到WebBrowser.Navigated
并解析了URL。我们专门在该网址中查找“closed = true”。如果找到,请关闭整个应用程序(包括WPF主机)。