好的,看来我要回答我自己的问题了;)
LoginButton 在内部使用 FacebookSessionClient 来登录/注销,而 FacebookSessionClient 实际上使用适当的 FacebookSessionCacheProvider 序列化会话状态。到目前为止,一切都很好。
诀窍是在页面加载时将任何现有会话状态设置为按钮。我最初确信这是不可能的,因为 CurrentSession 和 CurrentUser 的 LoginButton 属性是只读的。但经过进一步审查,我发现我实际上可以使用 SetValue 通过它们的依赖属性设置这些值。
我使用适当的事件处理程序从 LoginButton 跟踪会话和用户状态,如下所示:
private void OnSessionStateChanged(object sender, Facebook.Client.Controls.SessionStateChangedEventArgs e)
{
if (e.SessionState == Facebook.Client.Controls.FacebookSessionState.Opened)
{
App.CurrentSession = this.loginButton.CurrentSession;
}
else if (e.SessionState == Facebook.Client.Controls.FacebookSessionState.Closed)
{
App.CurrentSession = null;
// The control signals when user info is set (handled in OnUserInfoChanged below), but not when it
// is cleared (probably a bug), so we clear our reference here when the session ends.
//
App.CurrentUser = null;
}
}
private void OnUserInfoChanged(object sender, UserInfoChangedEventArgs e)
{
App.CurrentUser = this.loginButton.CurrentUser;
}
在页面加载时,我从缓存中获取会话状态(因此这在启动应用程序、恢复应用程序以及从另一个页面导航回此页面时有效)并使用 SetValue 恢复登录按钮状态。如果用户先前已登录,但令牌已过期(由于使用短期令牌,经常在启动时发生),我有一些附加逻辑可以自动重新验证。我也有逻辑在需要时重新加载 CurrentUser。这样做的结果是登录按钮在所有三种情况下都具有正确的状态。
private async void navigationHelper_LoadState(object sender, LoadStateEventArgs e)
{
this.loginButton.ApplicationId = Constants.FacebookAppId;
App.CurrentSession = FacebookSessionCacheProvider.Current.GetSessionData();
if ((App.CurrentSession != null) && (App.CurrentSession.Expires <= DateTime.UtcNow))
{
// User was previously logged in, but session expired. Log them in again...
App.CurrentSession = await App.FacebookSessionClient.LoginAsync(Constants.FacebookPermissions);
}
if (App.CurrentSession != null)
{
this.loginButton.SetValue(LoginButton.CurrentSessionProperty, App.CurrentSession);
if (App.CurrentUser == null)
{
FacebookClient client = new FacebookClient(App.CurrentSession.AccessToken);
dynamic result = await client.GetTaskAsync("me");
App.CurrentUser = new GraphUser(result);
}
}
if (App.CurrentUser != null)
{
this.loginButton.SetValue(LoginButton.CurrentUserProperty, App.CurrentUser);
}
}
我认为正确的解决方案是让 LoginButton 使用缓存提供程序获取会话状态并适当地初始化自身(至少在会话有效/未过期的情况下),这样它就可以在没有任何这些体操的情况下“神奇地”工作.