我想通过WinForms浏览器在WinForms中托管Silverlight控件,但为了使其工作,我需要一些方法让表单与Silverlight进行通信,反之亦然。是否可能通过JavaScript作为中间人让两者相互交互?也就是说,让表单与浏览器的JavaScript通信,再让它与Silverlight控件通信?是否有更好的方法?或者除了将代码编译为Silverlight和WPF之外还有其他方法吗?
我想通过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"
添加到您的<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 Forms应用程序调用CallMe()
方法:
public void CallToSilverlight()
{
webBrowser.InvokeScript("CallMe", new object[] { "testing 1 2 3" });
}
如果您真正需要做的只是在桌面应用程序中托管Silverlight,我建议您查看Jeremiah Morrill的SilverlightViewport项目。它允许您在WPF或XNA应用程序中嵌入Silverlight应用程序。它仍然处于非常初期阶段,但您可能会发现它有用。
这里有一张图片来引起您的兴趣: