一步一步学Silverlight 2系列(22):在Silverlight中如何用JavaScript调用.NET代码

概述

Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言Visual Basic, Visual C#, IronRuby, Ironpython,对JSON、Web Service、WCF以及Sockets的支持等一系列新的特性。《一步一步学Silverlight 2系列》文章将从Silverlight 2基础知识、数据与通信、自定义控件、动画、图形图像等几个方面带您快速进入Silverlight 2开发。

Silverlight中内置了对于HTML、客户端脚本等的支持。上一篇介绍在Silverlight中调用JavaScript,本文我将介绍在Silverlight中如何用JavaScript调用.NET代码。

使用RegisterScriptableObject

在Silverlight 2中提供了如下两个类型:

ScriptableMemberAttribute:允许我们在Silverlight把成员暴露给Script。

ScriptableTypeAttribute:允许我们在Silverlight把类型暴露给Script。

同时HtmlPage提供了RegisterCreateableType和RegisterScriptableObject方法,用来注册可被脚本使用的类型或者对象实例。有了上面这些,就可以做到在JavaScript中调用Silverlight。

看一个简单的示例,在这个示例中,我们期望通过JavaScript传递两个参数给Silverlight中的方法,由该方法计算出结果后显示在Silverlight中,如图所示:

TerryLee_Silverlight2_0103 

首先我们编写在Silverlight中的界面布局:

<StackPanel Background="#CDFCAE" Orientation="Horizontal">
    <Border CornerRadius="10" Width="100" Height="40" Margin="50 10 0 0">
        <TextBlock Text="结果显示:" FontSize="20" Foreground="Red"></TextBlock>
    </Border>
    <Border CornerRadius="10" Background="Green" Width="300" Height="40">
        <TextBlock x:Name="result" FontSize="20" Foreground="White"
                   Margin="20 5 0 0"></TextBlock>
    </Border>
</StackPanel> 

并在加载时注册一个脚本可调用的当前页面实例:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    HtmlPage.RegisterScriptableObject("Calculator", this);
}

编写一个Add方法,该方法将在JavaScript中被调用,必须为public,用ScriptableMember特性暴露给脚本。

[ScriptableMember]
public void Add(int x, int y)
{
    int z = x + y;
    this.result.Text = String.Format("{0} + {1} = {2}", x, y, z);
}

现在编写测试页中的内容,提供输入的input控件:

<div class="main">
    <input id="txt1" type="text" />
    <input id="txt2" type="text" />
    <input id="Button1" type="button" value="确 定"/>
</div>

编写JavaScript调用Silverlight中的方法,获取Silverlight插件,Calculator就是我们刚才所注册的实例:

<script type="text/javascript">
    function callSilverlight()
    {
        var slPlugin = $get('Xaml1');
        
        slPlugin.content.Calculator.Add($get('txt1').value,$get('txt2').value);
    }
</script>

在按钮单击事件中调用该方法

<input id="Button1" type="button" value="确 定" onclick="callSilverlight()" />

运行后结果:

TerryLee_Silverlight2_0103 

输入两个数后显示出结果:

 TerryLee_Silverlight2_0104

使用RegisterCreateableType

现在我们再看一下如何使用RegisterCreateableType。对上面的示例做一些简单的改动,在Silverlight项目中添加一个Calculator类,需要给它加上ScriptableType特性:

[ScriptableType]
public class Calculator
{
    [ScriptableMember]
    public int Add(int x, int y)
    {
        return x + y;
    }
}

在页面加载时修改为如下代码,指定一个别名和要注册的类型:

HtmlPage.RegisterCreateableType("calculator", typeof(Calculator));

这样在JavaScript中就可以这样进行调用了,先创建一个之前注册为ScriptableType的实例,再调用它的相关方法:

<script type="text/javascript">
    function callSilverlight()
    {
        var slPlugin = $get('Xaml1');
        var cal = slPlugin.content.services.createObject("calculator");
        
        alert(cal.Add($get('txt1').value,$get('txt2').value));
    }
</script>

运行结果如下,没有问题:

TerryLee_Silverlight2_0105 

结束语

本文介绍了如何在JavaScript中调用Silverlight,通过前面几篇文章的介绍,如对DOM的操作、在Silverlight中调用JavaScript、在JavaScript中调用Silverlight等,可以看到,Silverlight与浏览器之间交互有着很好的支持,后面将继续介绍其它内容。

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
标签: Silverlight
posted @ 2008-03-13 17:47 TerryLee 阅读(12150) 评论(58) 编辑 收藏

 回复 引用 查看   
#1楼 2008-03-13 17:55 菜菜灰      
沙发
 回复 引用 查看   
#2楼[楼主] 2008-03-13 17:56 TerryLee      
@菜菜灰
:)

 回复 引用   
#3楼 2008-03-13 17:57 JeffreyChen[未注册用户]
速度太快了,明天再来学习,下班了,呵...
 回复 引用 查看   
#4楼 2008-03-13 17:58 jillzhang      
学习的都不如你写的快了,太强了
 回复 引用 查看   
#5楼[楼主] 2008-03-13 18:02 TerryLee      
@JeffreyChen
@jillzhang
谢谢两位的支持:)

 回复 引用 查看   
#6楼 2008-03-13 18:03 阿布      
:D
 回复 引用 查看   
#7楼 2008-03-13 18:08 neuhawk      
比较关心
1,右键
2,打印

 回复 引用 查看   
#8楼 2008-03-13 18:09 永春      
佩服,忒快了
 回复 引用 查看   
#9楼[楼主] 2008-03-13 18:25 TerryLee      
@阿布
:)

 回复 引用 查看   
#10楼[楼主] 2008-03-13 18:25 TerryLee      
@neuhawk
右键现在似乎不好实现

 回复 引用 查看   
#11楼[楼主] 2008-03-13 18:26 TerryLee      
@永春
:)

 回复 引用 查看   
#12楼 2008-03-13 18:30 youhok      
学习!

目前正在用 sl 做一个关系图程序,也是打印问题没有眉目。
右键菜单可以用 canvas模拟吧,似乎没太好的办法,希望尽快能出来弹出菜单的控件。

 回复 引用   
#13楼 2008-03-13 18:50 5254341[未注册用户]
--引用--------------------------------------------------
jillzhang: 学习的都不如你写的快了,太强了
--------------------------------------------------------
是呀,老大真是太强了

 回复 引用 查看   
#14楼[楼主] 2008-03-13 19:04 TerryLee      
@youhok
现在右键菜单确实没有很好的方法

 回复 引用 查看   
#15楼[楼主] 2008-03-13 19:05 TerryLee      
@5254341
:)

在搭配上DLR就更酷,在页面上现在用多种语言混合编码操纵页面的DOM,包括javascript,ironpython,ironruby,vbx,ManagedJs. 可看看这个项目http://www.codeplex.com/DLRScript
 回复 引用 查看   
#17楼 2008-03-14 08:02 生鱼片      
支持
 回复 引用 查看   
#18楼 2008-03-14 08:14 小庄      
打印是个问题;多窗口管理也是个问题,客户端代码动态下载并运行更是个问题!搞个sl做的windows desktop还有很多问题要解决啊!
 回复 引用 查看   
#19楼[楼主] 2008-03-14 08:36 TerryLee      
@自由、创新、研究、探索……
有空看看这个项目,呵呵,多谢:)

 回复 引用 查看   
#20楼[楼主] 2008-03-14 08:37 TerryLee      
@生鱼片
谢谢:)

 回复 引用 查看   
#21楼[楼主] 2008-03-14 08:37 TerryLee      
@小庄
多窗口是不是可以通过加载UserControl来模拟。。。

 回复 引用 查看   
#22楼 2008-03-14 09:22 闲蚁      
请问一下楼主, 我在用Application.GetResourceStream方法获取Build action为Resource的文件时为什么老是返回null, 看了MSDN上说相对路径要用"SilverlightApplication;component/test.txt",还是不行,只有build action为content的才获取得到,楼主能不能帮忙看一下, :)
 回复 引用 查看   
#23楼 2008-03-14 11:11 状元      
想问一下,
我要是部署到买的空间上,
需要空间支持silverlight
还是说只要普通的空间就行?

 回复 引用 查看   
#24楼 2008-03-14 13:38 Scott Xu(南方小鬼)      
有个问题请教一下,现在有两个页面A和B,A以POST方式提交给B,B页面中的SL如何获得提交过来的FORM?
 回复 引用 查看   
#26楼[楼主] 2008-03-14 22:52 TerryLee      
@闲蚁
我有空测试一下吧,我没注意这一点:)

 回复 引用 查看   
#27楼[楼主] 2008-03-14 22:52 TerryLee      
@状元
现在打包为xap文件,似乎普通的就行吧,应该跟flash差不多

 回复 引用 查看   
#28楼[楼主] 2008-03-14 22:53 TerryLee      
@Scott Xu(南方小鬼)
用WebRequest应该可以吧

 回复 引用 查看   
#29楼 2008-03-16 18:30 状元      
@TerryLee
谢谢!

 回复 引用 查看   
#30楼[楼主] 2008-03-16 23:29 TerryLee      
@状元
不过提供空间的IIS服务器应该设置一下对.xap文件的处理.

 回复 引用 查看   
#31楼 2008-03-26 15:46 东吴居士      
请问楼主sl在firefox中文字体显示不出来如何解决?
What is this line:
var cal = slPlugin.content.services.createObject("calculator");

"services" is not registered anywhere.. so I get invalid alias found, and the example does not work.

 回复 引用 查看   
#33楼 2008-05-18 16:09 吴博      
第一个例子试验失败。
在测试页中“slPlugin”为[object],“slPlugin.content”为undefined。

有本篇教程源码下载吗?

 回复 引用   
#34楼 2008-06-11 15:38 Helloword[未注册用户]
今天才发现,有点 XXX的感觉。
已经天天看。写的太棒了

 回复 引用   
#35楼 2008-07-07 19:09 richardyjj[未注册用户]
请问如何在SL中触发控件打开一个新的窗口,HtmlPage.Window.Navigate(new Uri(XXX),"new")是否可行,如果可行那如何在SL与新窗口间进行数据传递呢,例如打开的page是个form,如何在submit之后将参数传回SL
 回复 引用 查看   
#36楼[楼主] 2008-07-08 16:17 TerryLee      
@吴博
有空把代码发给我,看一下

 回复 引用 查看   
#37楼[楼主] 2008-07-08 16:17 TerryLee      
@Helloword
:)

 回复 引用 查看   
#38楼[楼主] 2008-07-08 16:24 TerryLee      
@richardyjj
SL与页面之间的传参有很多种方式,可以使用InitParams或者QueryString等。

 回复 引用 查看   
#39楼 2008-07-31 10:30 monkey-猴子      
--引用--------------------------------------------------
吴博: 第一个例子试验失败。
<br>在测试页中“slPlugin”为[object],“slPlugin.content”为undefined。
<br>
<br>有本篇教程源码下载吗?
--------------------------------------------------------
我遇到的也是这个问题,请问楼主这个问题怎么解决的哈?

 回复 引用 查看   
#40楼[楼主] 2008-08-01 00:52 TerryLee      
@monkey-猴子
var slPlugin = $get('Xaml1');
看看这里,Silverlight控件的ID是否正确

 回复 引用 查看   
#41楼 2008-10-13 15:32 threeG      
并在加载时注册一个脚本可调用的当前页面实例:

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.RegisterScriptableObject("Calculator", this);
}

这段代码下在哪里啊?谢谢啊!

 回复 引用   
#42楼 2008-11-13 00:36 冻结[未注册用户]
@threeG
直接写在构造函数Page里就可以,或者:
public Page()
{
InitializeComponent();
this.Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
// 写在这里
}

 回复 引用   
#44楼 2009-08-20 11:10 qingtian1220[未注册用户]
我使用的是silverlight3,为什么我的调用就是不行呢?
 回复 引用   
#45楼 2009-08-26 13:12 ajax001[未注册用户]
我一看,怎么和Ajax一样呢?
 回复 引用 查看   
#46楼 2009-09-16 15:55 www_scott      
我的也是SL3,也是行呢,同MONKEY的问题
 回复 引用   
#47楼 2009-11-02 10:44 lucine[未注册用户]
我用的是Silverlight3,调试失败,如何解决啊
 回复 引用 查看   
#48楼 2010-04-27 20:57 mjsky      
谢谢楼主
 回复 引用 查看   
#49楼 2010-08-13 22:41 fisea      
我也是Siverlight3,调试失败,似乎没有Siverlight控件。
 回复 引用 查看   
#50楼 2010-10-18 10:21 heiyumars      
霸占50楼。
 回复 引用 查看   
#51楼 2011-06-03 01:35 软白      
到C#的时候 提示方法为空, 不知道为什么
其他地方跟你的一样

 回复 引用 查看   
#52楼 2011-06-03 11:37 kingdizzy      
楼主,你这个方法其实并不是在Silverlight中如何用JavaScript调用.NET代码,而是在Aspx中通过JavaSript调用Silverlight中的代码,反了吧!