14.4 与浏览器交互
在最初的Silverlight 1中只能使用JavaScript来编程,从Silverlight 2开始改变了这一状况。但是仍然有很多情况下需要在Silverlight中控制HTML和JavaScript代码,或者从JavaScript中调用.NET方法。这两种情况可以使用System.Windows.Browser命名空间来处理,下面介绍具体的实现方法。
14.4.1 调用HTML页面
为了测试从Silverlight中调用HTML页面,首先需要创建一个Silverlight项目,再到XAML中布局和编写调用HTML代码,最后在HTML页面中设置显示位置。具体步骤如下。
【范例2】
(1)新建一个名为SilverlightApplication1的Silverlight应用程序。
(2)打开MainPage.xaml在界面设计器上使用Grid控件制作一个4行2列的表格,并向单元格中填充内容。最终代码如下所示。
<Grid Background="#FF28ABB2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="auto"></ColumnDefinition> <ColumnDefinition Width="*"></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <TextBlock Margin="3" Grid.Column="1" FontSize="20">用户注册</TextBlock> <TextBlock Margin="3" Grid.Row="1">用户昵称:</TextBlock> <TextBox Height="23" Width="200" HorizontalAlignment="Left" Grid.Column="1" Grid.Row="1" Name="txtName" /> <TextBlock Margin="3" Grid.Row="2">用户密码:</TextBlock> <TextBox Height="23" Width="200" HorizontalAlignment="Left" Grid.Column="1" Grid.Row="2" Name="txtPass"/> <Button Grid.Column="1" Grid.Row="3" Content="确定" HorizontalAlignment="Left" Width="75" Click="button1_Click"/> </Grid>
上述代码主要包含两个用于输入的TextBox控件以及一个用于提交的Button控件。
(3)在MainPage.xaml.cs文件中编写按钮的单击事件处理方法button1_Click,代码如下所示。
private void button1_Click(object sender, RoutedEventArgs e) { HtmlDocument doc = HtmlPage.Document; //创建一个表示HTML页面的对象 HtmlElement el1 = doc.GetElementById("dvResult"); //获取HTML页面上的对象 string html = "<ul><li>用户名:" + txtName.Text + "</li><li>用户密码:" + txtPass.Text + "</li></ul>"; //获取用户输入的内容,并组成HTML字符串 el1.SetProperty("innerHTML", html); //插入内容 }
上述代码是Silverlight调用HTML页面的核心代码,首先通过HtmlPage.Document属性创建一个表示HTML页面的对象doc,再调用该对象的GetElementById()方法从HTML页面获取ID为dvResult的对象,然后通过SetProperty()方法设置显示的HTML代码。整个过程与使用HTML中的DOM模型非常类似。
注意
必须先使用“using System.Windows.Browser”语句引入HtmlPage所在的命名空间,否则将出错。
(4)经过上面的步骤Silverlight项目的工作就完成了。下面打开Web项目中用于测试Silverlight的HTML页面,并在<form>标记下添加如下代码。
如下是由Silverlight中返回的用户信息: <div id="dvResult"></div> <hr/>
上述代码中最主要的是id为dvResult的元素,因为最终由Silverlight返回的内容将显示到该元素内。
(5)编译Silverlight项目,并运行HTML测试页面。首次运行时,由于没有设置任何内容显示效果如图14-8所示。
图14-8 首次运行时
(6)在Silverlight中输入用户名和密码,再单击【确定】按钮,此时显示效果如图14-9所示。
图14-9 调用效果
提示
使用System.Windows.Browser命名空间中的类可以访问HTML中的所有信息。其中最常用的HtmlPage类、HtmlDocument类、HtmlWindow类和HtmlObject类,分别用于访问浏览器信息、Cookie页面中的元素和样式表,可以读取和修改内容。
14.4.2 调用Silverlight
如果希望在HTML页面可以调用Silverlight有两种方法,第一种是使用HtmlElement对象的AttachEvent()方法,另一种是使用ScriptableMember特性。下面分别介绍这两种方法的具体实现过程。
【范例3】
假设在Silverlight项目的MainPage.xaml中有如下的布局代码。
<Canvas Background="#FFC96767"> <TextBox Name="textbox1" Height="23" TextWrapping="Wrap" VerticalAlignment="Top" Text="TextBox1" Width="258" Canvas.Left="59" Canvas.Top="36"/> <Button Content="同步" Width="75" Click="Button_Click_1" Canvas.Left="59" Canvas.Top="80"/> <TextBox Name="textbox2" Height="23" Canvas.Left="59" Text Wrapping="Wrap" Text="TextBox2" Width="258" Canvas.Top="131"/> </Canvas>
在后台文件已经实现了单击【同步】按钮时将textbox1中的内容复制到textbox2中。现在要实现单击HTML页面中的一个按钮完成同步功能,步骤如下。
(1)在测试Silverlight的HTML页面中使用如下代码添加一个用于单击的按钮。
<input type="button" value="在HTML中实现同步功能" id="button1" />
上述代码创建一个id为button1,值为“在HTML中实现同步功能”的HTML按钮。
(2)进入MainPage.xaml的后台cs文件,在构造函数中找到HTML按钮button1,并注册单击事件处理函数。具体实现代码如下。
public MainPage() { InitializeComponent(); HtmlDocument doc = HtmlPage.Document; //获取HTML页面 HtmlElement button1 = doc.GetElementById("button1"); //找到button1 button1.AttachEvent("onclick", onHtmlButtonClick); //为onclick事件注册处理函数 }
上述代码实现了单击HTML页面button1时执行onHtmlButtonClick()函数。
(3)编写onHtmlButtonClick()函数,实现复制功能。具体实现代码如下。
private void onHtmlButtonClick(object sender, HtmlEventArgs e) { textbox2.Text = textbox1.Text; //使textbox2的内容与textbox1相同 }
(4)现在运行HTML页面,单击【在HTML中实现同步功能】按钮查看onHtmlButtonClick()函数执行效果。
【范例4】
为了使用ScriptableMember特性,需要在Silverlight后台文件中将可以被HTML页面调用的方法添加“[ScriptableMember]”进行修饰。假设,以MainPage.xaml.cs中有一个ToUpper()方法用于将字符串转换为大写,应用ScriptableMember特性后的代码如下所示。
[ScriptableMember] public string ToUpper(string s) //转换大写方法,参数s为要转换的字符串 { return s.ToUpper(); //返回转换后的大写字符串 }
在这里要注意,应用ScriptableMember特性的方法必须具有public作用域,且带有一个返回值。
如果一个类中包含可在HTML页面中调用的脚本,还必须在后台进行注册,以便Silverlight脚本引擎能找到该类型。注册方法是调用HtmlPage类的RegisterScriptableObject()方法。该方法的第一个参数是JavaScript中用于查找对象的键名,第二个参数定义了用于访问的成员实例(通常为this)。
在本示例中使用的注册代码如下。
public MainPage() { InitializeComponent(); HtmlPage.RegisterScriptableObject("ScriptKey", this); //指定一个键名来注册脚本 }
现在便可以在HTML中访问Silverlight中的ToUpper()方法了。为了使HTML能找到ToUpper()方法,首先要找到Silverlight控件,这需要对默认生成的代码进行修改。为测试Silverlight的object标记添加一个id属性,并同时添加用于测试的HTML代码,最终代码如下所示。
请输入一个字符串:<input type="text" id="inWords" /> <input type="button" value="转换" onclick="transfer()" /><br /> 转换结果如下:<div id="dvResult"></div> <div id="silverlightControlHost"> <object id="plugin" data="data:application/x-silverlight-2, " type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value="ClientBin/SilverlightAppli cation2.xap" /> <param name="onError" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="5.0.61118.0" /> <param name="autoUpgrade" value="true" /> <a href="http://go.microsoft.com/fwlink/? LinkID=149156&v= 5.0.61118.0" style="text-decoration: none"> <img src="http://go.microsoft.com/fwlink/? LinkId=161376" alt="获取 Microsoft Silverlight" style="border-style: none" /> </a> </object> <iframe id="_sl_historyFrame" style="visibility: hidden; height: 0px; width: 0px; border: 0px"></iframe> </div>
当单击【转换】按钮之后会调用HTML的transfer()方法,该方法通过id属性找到Silverlight,再使用指定的键名获取后台文件的引用,接着调用ToUpper()方法并显示转换后的结果。最终代码如下所示。
function transfer() { var ClientObject = document.getElementById("plugin"); var ServerObject = ClientObject.content.ScriptKey; var str = document.getElementById("inWords").value; var result = ServerObject.ToUpper(str); document.getElementById("dvResult").innerHTML = result; }
最后编译整个Silverlight项目,然后运行HTML页面测试转换效果,这里不再演示。