非常非常简单的MVVM问题

时间:2011-05-15 17:19:18

标签: c# silverlight windows-phone-7 mvvm

我正试图制作我的第一个Silverlight应用程序,但是我无法使用LogOn功能,你能帮助我吗?对于你们所有人来说这应该是非常简单的,我将向你展示我的两个文件:LogOn.xaml.cs和LogOnViewModel.cs

显然问题是UserId在我需要的时候没有及早设置为LogOn.xaml.cx,你可以帮助我使它工作,这会提升我的时刻: - )

public partial class LogOn : PhoneApplicationPage
{
    public LogOn()
    {
        InitializeComponent();
        this.DataContext = LogOnViewModel.Instance;
    }

    private void btnLogOn_Click(object sender, RoutedEventArgs e)
    {
        if ((!string.IsNullOrEmpty(txtEmailAddress.Text)) && (!string.IsNullOrEmpty(txtPassword.Password)))
        {
            txbLogonMessage.Text = "";
            LogOnViewModel.Instance.UserLogin(txtEmailAddress.Text, txtPassword.Password);

            if (LogOnViewModel.Instance.UserId > 0)
                NavigationService.Navigate(new Uri("/_2HandApp;component/Views/Main.xaml", UriKind.Relative));
            else
                txbLogonMessage.Text = "Login was unsuccessful. The user name or password provided is incorrect. Please correct the errors and try again. ";
        }
    }
}


public sealed class LogOnViewModel : INotifyPropertyChanged
{
    public static LogOnViewModel Instance = new LogOnViewModel();
    //public static int userId;

    private SHAServiceClient WS;

private int userId;
    public int UserId
    {
        get
        {
            return userId;
        }

        set
        {
            userId = value;
            this.RaisePropertyChanged("UserId");
        }
    }


private LogOnViewModel()
    {
        WS = new SHAServiceClient();
        WS.UserLoginCompleted += new EventHandler<UserLoginCompletedEventArgs>(WS_UserLoginCompleted);
    }

    void WS_UserLoginCompleted(object sender, UserLoginCompletedEventArgs e)
    {
        if (e.Error == null)
        {
            this.UserId = e.Result;
        }
    }


    public void UserLogin(string email, string password)
    {
        WS.UserLoginAsync(email, password);
    }

/* Implementing the INotifyPropertyChanged interface. */
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null))
        {
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

2 个答案:

答案 0 :(得分:4)

问题的原因是@flq强调的。您正在进行异步调用,这意味着您将无法立即获得预期结果(在您的情况下,正在分配UserId),而是您可以将其下载到{{1}在异步任务完成时处理事情的事件(或提供回调)。

现在,执行此操作的“MVVM方式”(或者至少我会做的事情)如下:首先,去获取MVVM Light!它是一个轻量级的MVVM框架,非常有用。您应该让您的ViewModel类从MVVMLight实现Completed基类,这将提供更改通知和消息以及其他有用的东西。然后,您应该将登录功能封装在命令中,以便能够从xaml连接它,因为您可以使用MVVMLight的ViewModelBase。登录完成后,您只需向视图发送消息即可让它知道(以非常分离的方式),视图可以简单地启动导航。

以下是代码:

RelayCommand

表示xaml:

public class LogOnViewModel : ViewModelBase
{
    private SHAServiceClient WS;
    public LogOnViewModel()
    {
       WS = new SHAServiceClient();
       WS.UserLoginCompleted += new EventHandler<UserLoginCompletedEventArgs>(WS_UserLoginCompleted);
       LoginCommand = new RelayCommand(UserLogin);
    }
    private int userId;
    public int UserId
    {
       get { return userId; }
       set
       {
          userId = value;
          RaisePropertyChanged(()=>UserId);
       }
    }
    private int password;
    public int Password
    {
       get { return password; }
       set
       {
          password = value;
          RaisePropertyChanged(()=>Password);
       }
    }
    private int username;
    public int Username
    {
       get { return username; }
       set
       {
          username = value;
          RaisePropertyChanged(()=>Username);
       }
    }
    private int loginErrorMessage;
    public int LoginErrorMessage
    {
       get { return loginErrorMessage; }
       set
       {
          loginErrorMessage = value;
          RaisePropertyChanged(()=>LoginErrorMessage);
       }
    }
    void WS_UserLoginCompleted(object sender, UserLoginCompletedEventArgs e)
    {
       if (e.Error == null)
       {
          this.UserId = e.Result;
          // send a message to indicate that the login operation has completed
          Messenger.Default.Send(new LoginCompleteMessage());
       }
    }
    public RelayCommand LoginCommand {get; private set;}
    void UserLogin()
    {
       WS.UserLoginAsync(email, password);
    }
}

在后面的代码中:

<TextBox Text="{Binding Username, Mode=TwoWay}"/>
<TextBox Text="{Binding Password, Mode=TwoWay}"/>
<Button Command="{Binding LoginCommand}"/>
<TextBlock Text="{Binding LoginErrorMessage}"/>    

您可以看到ViewModel中有更多(但简单明了)的代码,而后面的代码则更少。这也利用了DataBinding,它位于MVVM的核心。

希望这会有所帮助:)

PS:在这种情况下,LoginCompletedMessage类只是一个空类(仅用于定义类型消息),但您可以使用它来发送更多信息(也许您仍希望拥有UserId已发送)

答案 1 :(得分:1)

好吧,您正在调用登录WS.UserLoginAsync的异步版本,这意味着执行会继续执行,并且在您检查时确实没有用户ID。

你在这里并没有真正做MVVVM,但无论如何,让我们顺其自然。在登录过程结束时(WS_UserLoginCompleted)引发“Viewmodel”上的事件。您可以处理它并在该事件的事件处理程序中触发导航。

相关问题