Silverlight在Winforms中的托管

11

我想通过WinForms浏览器在WinForms中托管Silverlight控件,但为了使其工作,我需要一些方法让表单与Silverlight进行通信,反之亦然。是否可能通过JavaScript作为中间人让两者相互交互?也就是说,让表单与浏览器的JavaScript通信,再让它与Silverlight控件通信?是否有更好的方法?或者除了将代码编译为Silverlight和WPF之外还有其他方法吗?

4个回答

16

我认为使用Windows Forms 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 Forms项目内的全部内容。在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方法:

注意:原文中的代码标记仅为了突出显示代码内容,并非HTML标签,因此不需要保留。
<script type="text/javascript">
    function CallMe(message) {
        var control = document.getElementById('silverlightControl');
        control.Content.Page.CallMeInSilverlight(message);
    }
</script>

现在我们可以这样从Windows Forms应用程序调用CallMe()方法:

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

太棒了!我希望你能想出如何从WebBrowser让它在WinForm中工作。我还没有看到其他人在网上做过这个(甚至尝试过...),所以如果你能解决它,那就太好了。 - NotDan
你曾经解决过如何从主机表单调用Silverlight吗? - Shrike

1

1

看一下Desklighter。虽然不完全符合你的要求,但它证明了这是可能的吗?


0
在Winform应用程序中使用Silverlight听起来像是坏消息。这意味着您需要在单个应用程序中运行不同的CLR,并且必须处理大量添加的复杂性才能使其正常工作。如果可能,请考虑在应用程序中使用完整的WPF,这里有一个link向您展示如何做到这一点。

Silverlight使用的CoreCLR支持与其他CLR一起在进程中运行,因此这不是一个问题。 - Judah Gabriel Himango
有趣,谢谢分享。我想强调的是,虽然你可以这样做,但这可能不是明智之举。不过,这仍然是一种巧妙地利用技术的方式。 - smaclell
嗯...CoreCLR将在客户端运行。它不会在服务器上运行,对吧? - AnthonyWJones
有时候不同的技术需要相互交互。这就是为什么微软创造了这种能力。在理想的世界中,所有应用程序都应该是单一功能应用程序。我的许多客户都是企业,一旦开始看到需求,几乎没有其他选择。当然,除非有更好的技术,然后仍然由程序员知道如何实现它们。 - IEnumerable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接