【问题标题】:Embedded Silverlight app inside .NET desktop app and communication between them.NET 桌面应用程序中的嵌入式 Silverlight 应用程序以及它们之间的通信
【发布时间】: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


    【解决方案1】:

    目前没有仅限托管的互操作。您提到的两个选项(DOM 桥上的 JavaScript 互操作,或 COM 托管)都是存在的。

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

    【讨论】:

      【解决方案2】:

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

      例如,我们有一个托管在 WPF WebBrowser 控件中的 Silverlight 应用程序。我们想知道用户何时单击 Silverlight 应用程序中的“关闭”按钮。我们将事件处理程序附加到WebBrowser.Navigated 并解析 URL。我们专门在那个 url 中寻找“close=true”。如果找到,请关闭整个应用程序(包括 WPF 主机)。

      Silverlight App inside WPF WebBrowser ?

      【讨论】:

      • 谢谢,这很好,但我需要一直在主机和 SL 应用程序之间进行通信。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-03
      • 1970-01-01
      相关资源
      最近更新 更多