我想通过winforms浏览器在winforms中托管一个silverlight控件,但是为了工作,我需要一些方法让表单与silverlight交谈,以及相反的方式.是否有可能以两种方式使用JavaScript作为中间人相互交互?即,让表单与浏览器的javascript说话,并让它与silverlight控件说话?有没有更好的办法?甚至是一种方式?(除了将代码编译为silverlight和wpf)
我认为使用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"
到元素中:
document.getElementById('silverlightControl').Content.Page.CallMeInSilverlight("testing 1 2 3");
注意Page
财产?这就是RegisterScriptableObject()
给我们的电话.现在,让我们将它包装成一个整洁的JavaScript方法:
现在我们可以CallMe()
从Windows Forms应用程序中调用该方法,如下所示:
public void CallToSilverlight() { webBrowser.InvokeScript("CallMe", new object[] { "testing 1 2 3" }); }