我正试图制作我的第一个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));
}
}
}
答案 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”上的事件。您可以处理它并在该事件的事件处理程序中触发导航。