将 Silverlight 与浏览器的后退按钮集成





4.00/5 (3投票s)
描述如何使 Silverlight 应用程序像传统的 Web 应用程序一样运行 - 具有使用浏览器后退/前进导航按钮的导航状态。
引言
Silverlight 是一项将更丰富的用户体验带到 Web 客户端的强大技术。但是,由于 Silverlight 是网页上的一个控件,因此可能会出现以下情况:Silverlight 控件内已发生逻辑导航(例如,用户单击了一个导致面板更新的按钮),但实际上未发生网页导航(这对于 AJAX 开发人员来说很熟悉)。由于 Web 的主要范例是导航堆栈,因此用户希望能够通过按下大型、方便的后退按钮来“后退”,就像他们访问的大多数其他网站一样。最令人不快的是,这样做可能会将他们从控件完全导航到他们访问的上一个页面,从而破坏控件中存在的所有状态。
已经开发了各种技术来尝试将预期用户行为的方块钉子,基于 Web 1.0,放入不使用相应浏览器导航堆栈的 Web 2.0 风格技术的圆孔中。在这些技术中,也许最优雅的解决方案是操纵浏览器的导航堆栈 - 以便按下后退按钮确实将 Silverlight 控件“后退”到之前的逻辑状态。这完全符合用户对 Web 行为方式的期望,并具有额外的优势,即可以使用浏览器工具栏区域进行应用程序特定的逻辑命令(后退和前进按钮可能最终会出现在控件本身上)。
事实证明,通过隐藏的 IFRAME 以这种方式操纵浏览器的导航堆栈非常容易。每个逻辑导航点都存储在此 IFRAME
中,然后在用户按下后退按钮时通过 JavaScript 恢复到控件。来自 Yahoo 用户界面 (YUI) 团队的优秀人士已将这种 IFRAME
的使用包装在一个方便(免费且不受限制)的 JavaScript 模块中,该模块适用于大多数浏览器和平台。
本文介绍了如何将具有不同可导航状态的 Silverlight 控件与 YUI 库模块结合使用,以重现熟悉的 Web 浏览器范例。
Using the Code
要在您的页面上使用 YUI History,您首先需要包含 YUI JavaScript 库。这些可以从 这里 获取。
<script type="text/javascript" src="yui/yahoo-dom-event.js"></script>
<script type="text/javascript" src="yui/history-min.js"></script>
您还需要添加隐藏的 IFRAME
和隐藏的 INPUT
,这些将用于存储控件状态
<style type="text/css">
#yui-history-iframe {
position:absolute;
top:0; left:0;
width:1px; height:1px;
visibility:hidden;
}
</style>
...
<iframe id="yui-history-iframe" src="blank.htm"></iframe>
<input id="yui-history-field" type="hidden"/>
从 JavaScript 到 Silverlight 控件的通信通过 JavaScriptBridge
类进行。每当浏览器的导航状态更改时,JavaScript 将调用 LoadState
方法。
public class JavaScriptBridge
{
Page _page;
public JavaScriptBridge(Page page)
{
_page = page;
}
[ScriptableMember]
public void LoadState(string state)
{
if (String.IsNullOrEmpty(state))
_page.SetInitialState();
else
_page.LoadState(state);
}
}
private void Application_Startup(object sender, StartupEventArgs e)
{
Page page = new Page();
this.RootVisual = page;
JavaScriptBridge bridge = new JavaScriptBridge(page);
HtmlPage.RegisterScriptableObject("jsBridge", bridge);
string initialState = HtmlPage.Window.Invoke("GetInitialState") as string;
if (initialState != null)
bridge.LoadState(initialState);
}
由于 YUI 历史记录管理器和 Silverlight 控件的加载事件之间存在竞争条件,因此需要进行一些逻辑来确保控件始终使用初始起始状态进行初始化(该状态可能已通过查询字符串设置)。
控件调用 GetInitialState
,如果 YUI 已加载,则返回初始状态,否则返回 null
。当 YUI 加载 (_Init
) 时,它会检查控件是否已加载。如果是,它会告诉控件页面的初始状态。
YAHOO.util.Event.onDOMReady
事件处理程序将在页面 DOM 加载后触发,这是 YUI 历史记录模块初始化的时候。
var g_initialState = null, g_controlHasLoaded = false;
function GetInitialState() {
g_controlHasLoaded = true;
return g_initialState;
}
function LoadContent(state) {
try {
YAHOO.util.History.navigate("q", state.toString());
} catch (e) {
_LoadContent(state);
}
}
function _LoadContent(state) {
if (g_controlHasLoaded) {
var ctrl = document.getElementById("silverlightControl");
ctrl.Content.jsBridge.LoadState(state);
} else
g_initialState = state;
}
function _Init() {
var state = YAHOO.util.History.getCurrentState("q");
if (typeof (state) == "string") {
if (g_controlHasLoaded)
_LoadContent(state);
else
g_initialState = state;
}
}
YAHOO.util.Event.onDOMReady(new function() {
var bookmarkedState = YAHOO.util.History.getBookmarkedState("q");
var queryState = YAHOO.util.History.getQueryStringParameter("q");
var initialState = bookmarkedState || queryState || "";
YAHOO.util.History.register("q", initialState, function(state) {
_LoadContent(state);
});
YAHOO.util.History.onReady(function() {
_Init();
});
// Initialize the browser history management library.
try {
YAHOO.util.History.initialize("yui-history-field", "yui-history-iframe");
} catch (e) {
_Init();
// web navigation will not be available
}
});
当控件要注册状态转换时,它会调用 LoadContent
JavaScript 函数。这将状态存储在 IFRAME
中,并在控件上触发一个回调,然后控件使用该回调转换到该状态。
internal void NavigateToState(string state)
{
HtmlPage.Window.Invoke("LoadContent", state);
}
仅此而已。运行示例应用程序时,您应该确保将“Default.aspx”设置为起始页,而不是自动生成的 HTML 测试页(该测试页没有必需的 JavaScript)。
您会注意到可以使用浏览器的“后退”和“前进”按钮在控件状态之间导航。您还可以通过查询字符串设置状态。因此,您应该始终验证传入状态以确保其有效。
历史
- 2009 年 5 月 11 日:第一个版本。