在将WebContext添加到ApplicationLifetimeObjects或等待App.Current.Startup事件之前,InitializeComponent()?

时间:2011-09-21 14:13:59

标签: .net silverlight architecture

我使用MVVM方法构建了 Silverlight 应用程序。 在我的ViewModel中,只有在用户使用LoggedIn 后才能加载一些数据,所以我需要拦截此事件以触发我的LoadData()。 使用默认配置,我的意思是在App.xaml.cs中:

public App()
    {
        InitializeComponent();

        // Create a WebContext and add it to the ApplicationLifetimeObjects
        // collection.  This will then be available as WebContext.Current.
        WebContext webContext = new WebContext();
        webContext.Authentication = new FormsAuthentication();
        //webContext.Authentication = new WindowsAuthentication();
        this.ApplicationLifetimeObjects.Add(webContext);

如果您尝试在ViewModel构造函数中订阅LoggedIn或LoggedOut事件,则会遇到一些问题:WebContext尚不存在。

所以我想......我先创建我的WebContext,然后在我的应用程序中使用InitializeComponents(),但这会让ExpressionBlend感到悲伤......

所以,这是我的解决方案,我想与你分享,因为我并不完全相信这是正确的方法:

App.Current.Startup += (sender, eventArgs) => 
        {
            WebContext.Current.Authentication.LoggedIn += WebContext_LoggedIn;
            WebContext.Current.Authentication.LoggedOut += WebContext_LoggedOut;
        };

在我的ViewModel ctor中,我订阅App.Current.Startup,我的委托将订阅我的ViewModel到Login事件,这样我没有更改我的App.xaml.cs,我肯定在WebContext时订阅Login事件存在... 所以:

private void WebContext_LoggedIn(object sender, AuthenticationEventArgs e)
    {
        LoadData();
    }

修改

在这种情况下,当我说我不应该改变InitializeComponent()与其余部分之间的顺序并且我需要监听特定事件时,我更感兴趣的是理解我是否正确触发我的LoadData()。

为了完整起见,我的重构是在我的ViewModel中摆脱这种依赖:

我创建了一条消息:

public class UserLoginStatusChangedMessage : MessageBase
{
    public bool IsLoggedIn { get; set; }
}

发送到这里:

private void Application_Startup(object sender, StartupEventArgs e)
    {
        // This will enable you to bind controls in XAML files to WebContext.Current
        // properties
        this.Resources.Add("WebContext", WebContext.Current);

        // This will automatically authenticate a user when using windows authentication
        // or when the user chose "Keep me signed in" on a previous login attempt
        WebContext.Current.Authentication.LoadUser(this.Application_UserLoaded, null);

        // Show some UI to the user while LoadUser is in progress
        this.InitializeRootVisual();

        WebContext.Current.Authentication.LoggedIn += (s, a) => 
        { 
            Messenger.Default.Send(new UserLoginStatusChangedMessage 
            { IsLoggedIn = true }); 
        };

        WebContext.Current.Authentication.LoggedOut += (s, a) => 
        {
            Messenger.Default.Send(new UserLoginStatusChangedMessage 
            { IsLoggedIn = false });
        };
    }

并在ViewModel ctor中收到它:

 Messenger.Default.Register<UserLoginStatusChangedMessage>(this, msg => 
        {
            if (msg.IsLoggedIn)
            {
                LoadData();
            }
        });

1 个答案:

答案 0 :(得分:1)

我建议使用某种在用户登录时发送消息的信使类.MVVMLight有一个易于使用的nice messenger class。然后,您只需在用户登录状态发生变化时发送消息,并在视图模型中订阅该事件,该事件需要知道用户是否已登录。

您可以检查WebContext以查看它是否已创建,如果用户在创建viewmodel时登录,则会创建它,然后只需使用这些消息来确定是否/何时更改。