.net 在将WebContext添加到ApplicationLifetimeObjects或等待App.Current.Startup事件之前,是否初始化组件()?

.net 在将WebContext添加到ApplicationLifetimeObjects或等待App.Current.Startup事件之前,是否初始化组件()?,.net,silverlight,architecture,.net,Silverlight,Architecture,我有一个使用MVVM方法构建的Silverlight应用程序在我的ViewModel中,只有在用户登录后才能加载一些数据,因此我需要截获此事件以触发我的LoadData()。 使用默认配置,我在App.xaml.cs中的意思是: public App() { InitializeComponent(); // Create a WebContext and add it to the ApplicationLifetimeObjects

我有一个使用MVVM方法构建的Silverlight应用程序在我的ViewModel中,只有在用户登录后才能加载一些数据,因此我需要截获此事件以触发我的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,然后在我的应用程序中初始化Components(),但这让ExpressionBlend很伤心

因此,这是我的解决方案,我想与大家分享,因为我不完全相信这是正确的方法:

App.Current.Startup += (sender, eventArgs) => 
        {
            WebContext.Current.Authentication.LoggedIn += WebContext_LoggedIn;
            WebContext.Current.Authentication.LoggedOut += WebContext_LoggedOut;
        };
在我的ViewModel中,我订阅了App.Current.Startup,我的代理将订阅我的ViewModel登录事件,这样我就没有更改我的App.xaml.cs,并且我确信在WebContext存在时订阅登录事件。。。 因此:

编辑

在这种情况下,我更感兴趣的是,当我说我不应该更改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中以如下方式接收:

 Messenger.Default.Register<UserLoginStatusChangedMessage>(this, msg => 
        {
            if (msg.IsLoggedIn)
            {
                LoadData();
            }
        });
Messenger.Default.Register(此消息=>
{
如果(msg.IsLoggedIn)
{
LoadData();
}
});

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


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

谢谢您的回答,是的,我通常使用messenger来完成这些事情,在本例中肯定更好。。。否则我就要打破这种模式了。在这种情况下,我更感兴趣的是理解我说的不应该更改InitializeComponent()和其余部分之间的顺序,并且我需要侦听某个特定事件来触发我的LoadData()时是否正确。我觉得您编辑的代码很好。如果只在不处于设计模式的情况下加载WebContext,可能会让Blend更快乐。MVVMLight也有一种方法来检查这一点。
 Messenger.Default.Register<UserLoginStatusChangedMessage>(this, msg => 
        {
            if (msg.IsLoggedIn)
            {
                LoadData();
            }
        });