void Application_Exit(object sender, EventArgs e){ HtmlPage.Window.Invoke("NotifyWebserviceOnClose", new[] { guid.ToString() });}
我们于是在应用程序的页面中调PageMethod方法,如下所示:
function NotifyWebserviceOnClose(identifier) { PageMethods.SignOff(identifier, OnSignOffComplete); }
通过PageMethod,我们可以更新所连接的客户列表,或者其它我们想做的事情:
[WebMethod][System.Web.Script.Services.ScriptMethod] public static void SignOff(string identifier){ System.Diagnostics.Debug.WriteLine("*** Signing Off: " + identifier);}
注意, Laurent,这种方法并不可靠。所以,你将需要自己去测试它。在火狐 3.5和 IE8,我已经在本地测试过。但是,您的结果可能会不同。
现在我想看看第二件事是当用户尝试关闭浏览器时,能够提供一些与用户的交互作用,取消或调用 web 服务;但在浏览器实际关闭之前。
我所做的是在页面的 body 标签中放置 onbeforeunload 事件,如图所示:
<body onbeforeunload="OnClose()">
于是我在JavaScript脚本中创建了一个OnCLose事件,如下所示:
function OnClose() { var plugin = document.getElementById("silverlightControl"); var shutdownManager = plugin.content.ShutdownManager; var shutdownResult = shutdownManager.Shutdown(); if (shutdownResult) { event.returnValue = shutdownResult; }}
这里我们看到,在Silverlight 应用程序APP类中创建了一个 ShutdownManager 类的实例。ShutdownManager 是一个类,当应用程序正在关闭时,该类能够执行一些任意的事务。通过调用toRegisterScriptableObject注册它,由它可以访问驻留网页。
void Application_Startup(object sender, StartupEventArgs e){ HtmlPage.RegisterScriptableObject("ShutdownManager", shutdownManager); this.RootVisual = new MainPage();}
ShutdownManager
ShutdownManager 有两个属性修饰。他们的是 SciptableType 和 ScriptableMember。正如下面我们所看到,它们用于允许通过Ajax 调用 ShutdownManager 类。
[ScriptableType]public class ShutdownManager{ [ScriptableMember] public string Shutdown() { string result = null; var page = (MainPage)Application.Current.RootVisual; if (page.Dirty) { var messageBoxResult = MessageBox.Show( "Save changes you have made?", "Save changes?", MessageBoxButton.OKCancel); if (messageBoxResult == MessageBoxResult.OK) { var waitingWindow = new WaitingWindow(); waitingWindow.Show(); waitingWindow.NoticeText = "Saving work on server. Please wait..."; page.SetNotice("Saving work on server. Please wait..."); var client = new ShutdownServiceClient(); client.SaveWorkCompleted += ((sender, e) => { waitingWindow.NoticeText = "It is now safe to close this window."; page.SetNotice("It is now safe to close this window."); page.Dirty = false; waitingWindow.Close(); }); client.SaveWorkAsync("Test id"); result = "Saving changes."; } else { result = "If you close this window you will lose any unsaved work."; } } return result; }}
在这里我们看到一旦调用 Shutdown 方法,我们测试(Silverlight) 主页内容是否是被修改过的。如果是这样,我们提示用户保存更改。如果要保存更改,我们将派遣我们使用一个服务客户端的异步 web 服务调用。关键的一点,请注意这里是我们正在返回一个字符串值,如果该主页内容被视为被修改过的。此字符串值然后指示 JavaScript 代码不会立即关闭该窗口。一旦调用将使之回到我们的 JavaScript onbeforeload 处理程序,我们将事件返回值 event.returnValue 赋值给字符串。如果此值不是空字符串,则将导致 web 浏览器显示一个对话框 ;问他们是否真的希望离开页面的用户。
图:浏览器提示“请确认...”的信息
在这个示例程序中 ,您会注意到我们模拟用户修改。即用户点击网页复选框表示网页内容被修改。
图:模拟在示例应用程序中用户修改数据的操作
不点击复选框,关闭浏览器将立即关闭,点击复选框
图:提示保存修改对话框
如果用户取消了操作,会发生什么?还记得我们在 JavaScript OnClose 函数中的事件返回event.returnValue 字符串。如果用户取消,则此值分配一个字符串值的"如果您关闭此窗口中,您将失去任何未保存的工作。我们可以看到浏览器是怎样选择并显示的字符串的,如下所示:
图:浏览器启动对话框提示用户
图:进度条提示用户正在保存
一旦用户点击确定保存更改对话框中,web 服务是几乎立即调用。为了使 web服务调用的发生,我们必须执行中断线程,以便我们的 Silverlight 应用程序有机会调度调用操作。我们用 JavaScript 警报调用可以做到这一点,或者正如我们看到在这里,我们分配 event.returnValue事件返回值,这将导致多相同的方式显示的对话框。