【问题标题】:Silverlight Hosted in Winforms在 Winforms 中托管的 Silverlight
【发布时间】:2008-10-13 17:34:32
【问题描述】:

我想通过 winforms 浏览器在 winforms 中托管一个 silverlight 控件,但为了使其工作,我需要某种方式让表单与 silverlight 对话,反之亦然。是否有可能以某种方式让两者使用 JavaScript 作为中间人进行交互?即,让表单与浏览器的 javascript 对话,并与 silverlight 控件对话?有没有更好的办法?或者根本就没有办法? (除了将代码编译为silverlight和wpf)

【问题讨论】:

    标签: c# javascript wpf winforms silverlight


    【解决方案1】:

    我认为使用 Windows 窗体 WebBrowser 控件是您最好的选择。为此,您需要将 Silverlight 应用程序放在网页上,然后将 WebBrowser 指向页面的 URI。

    为了防止您的 WebBrowser 控件表现得像 IE,我建议设置以下内容:

    webBrowser.AllowNavigation = false;
    webBrowser.AllowWebBrowserDrop = false;
    webBrowser.IsWebBrowserContextMenuEnabled = false;
    webBrowser.WebBrowserShortcutsEnabled = false;
    

    从 Silverlight 中调用表单上的方法非常容易。首先,您需要一个包含您想从 Silverlight 调用的所有方法的类。您可以使用表单本身或其他对象,但您需要使用 [ComVisible(true)] 属性标记类。然后将对象分配给 WebBrowser.ObjectForScripting 属性。这会将您的对象公开为网页上的“window.external”。

    [ComVisible(true)]
    public partial class Form1 : Form
    {
        ......
        webBrowser.ObjectForScripting = this;
        ......
        public void CallMeInForm(string something)
        {
            MessageBox.Show("Silverlight said: " + something);
        }
    }
    

    在您的 Windows 窗体项目中就是这样。在您的 Silverlight 应用程序中,您需要获取此 ObjectForScripting 并在其上调用方法。要调用上面示例中的方法,请使用以下行:

    using System.Windows.Browser;
    ......
    ScriptObject myForm = (ScriptObject)HtmlPage.Window.GetProperty("external");
    myForm.Invoke("CallMeInForm", "testing 1 2 3");
    

    Invoke 命令允许您将任意数量和类型的参数传递给您的函数,尽管我怀疑如果您尝试传递复杂的数据类型,它不会非常喜欢它。但如果你需要这样做,你总是可以使用序列化。

    从您的表单中调用 Silverlight 函数似乎是一个更狡猾的方向。我还没有完全弄清楚这一点。

    在您的 Silverlight 应用程序中,您还可以向网页公开函数。为此,请使用 HtmlPage.RegisterScriptableObject() 函数。同样,您可以使用要公开的方法传入任何类。但是,对于要公开的方法,您必须使用 [ScriptableMember] 属性对其进行标记。

    HtmlPage.RegisterScriptableObject("Page", this);
    ......
    [ScriptableMember]
    public void CallMeInSilverlight(string message)
    {
        HtmlPage.Window.Alert("The form said: " + message);
    }
    

    此时,您的方法在页面上暴露给 JavaScript,您可以这样调用它,假设您将 id="silverlightControl" 添加到您的 <object> 元素:

    document.getElementById('silverlightControl').Content.Page.CallMeInSilverlight("testing 1 2 3");
    

    注意到Page 属性了吗?这就是对RegisterScriptableObject() 的调用给我们的。现在,让我们把它包装成一个整洁的 JavaScript 方法:

    <script type="text/javascript">
        function CallMe(message) {
            var control = document.getElementById('silverlightControl');
            control.Content.Page.CallMeInSilverlight(message);
        }
    </script>
    

    现在我们可以从 Windows 窗体应用程序中调用 CallMe() 方法,如下所示:

    public void CallToSilverlight()
    {
        webBrowser.InvokeScript("CallMe", new object[] { "testing 1 2 3" });
    }
    

    【讨论】:

    • 太棒了!我希望你能弄清楚如何让它从 WebBrowser 工作到 WinForm。我还没有在网上看到其他人这样做(甚至尝试过......)所以如果你能弄明白那就太好了。
    • 你有没有想过如何从主机窗体调用 Silverlight?
    【解决方案2】:

    看看Desklighter。不完全是您正在寻找的东西,但它确实证明它应该是可能的?

    【讨论】:

      【解决方案3】:

      如果您真的只需要在桌面应用程序中托管 Silverlight,我建议您查看 Jeremiah MorrillSilverlightViewport 项目。它允许您在 WPF 或 XNA 应用程序中嵌入 Silverlight 应用程序。它仍然是 Alpha 版,但您可能会发现它很有用。

      来一张图让你胃口大开:

      http://i3.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=silverlightviewport&DownloadId=97946

      【讨论】:

        【解决方案4】:

        Winform 应用程序中的 Silverlight 听起来像是个坏消息。这意味着您在单个应用程序中运行到不同的 CLR,并且必须处理许多额外的复杂性才能使其工作。如果可能,请考虑在您的应用程序中使用完整的 WPF,而不是使用 link 向您展示如何操作。

        【讨论】:

        • Silverlight 使用的 CoreCLR 支持这种与其他 CLR 在进程中运行的场景,所以这不是问题。
        • 有意思,谢谢分享。我试图强调,虽然你可以做到,但这样做可能并不可取。仍然是一种让技术随心所欲的巧妙方法。
        • 嗯... CoreCLR 将在客户端上运行。它不在服务器上运行吗?
        • 有时各种技术必须交互。这就是为什么 MSFT 创造了这样做的能力。在理想世界中,所有应用程序都是单功能应用程序。我的许多客户都是企业,一旦您开始看到需求,几乎别无选择。当然,除非有更好的技术,否则程序员仍然需要知道如何实现它们。
        猜你喜欢
        • 1970-01-01
        • 2011-06-13
        • 2010-10-14
        • 1970-01-01
        • 2013-05-29
        • 2010-10-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多