Очень очень простая проблема MVVM - PullRequest
3 голосов
/ 15 мая 2011

Я пытаюсь создать свое самое первое приложение Silverlight, но я не могу заставить работать функцию входа в систему, можете ли вы мне помочь?Это должно быть очень просто для всех вас, я покажу вам два моих файла: 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 ]

4 голосов
/ 15 мая 2011

Причиной проблемы является то, что было выделено @flq.Вы делаете асинхронный вызов , что означает, что вы не получите ожидаемый результат сразу (в вашем случае назначается UserId), но вместо этого вы можете подписаться на событие Completed (или обеспечить обратный вызов), чтобы обрабатывать вещи, когда асинхронная задача завершается.

Теперь «MVVM-способ» сделать это (или, по крайней мере, то, что я хотел бы сделать) заключается в следующем: во-первых, иди, получи MVVMСвет!это легковесная структура MVVM, которая была бы очень полезна.Вы должны иметь свой класс ViewModel, реализующий базовый класс ViewModelBase из MVVMLight, это обеспечит уведомление об изменениях и обмен сообщениями, а также другие полезные вещи.Затем вы должны инкапсулировать функциональность входа в команду, чтобы иметь возможность подключить ее из xaml, для этого вы можете использовать MVVMLight's RelayCommand.Как только вход в систему завершен, вы можете просто отправить сообщение вашему представлению, сообщив ему об этом (довольно несвязно), и представление может просто инициировать навигацию.

Вотбиты кода для этого:

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);
    }
}

для xaml:

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

в коде:

public partial class LogOn : PhoneApplicationPage
{
    public LogOn()
    {
        InitializeComponent();
        this.DataContext = new LogOnViewModel();
        Messenger.Default.Register<LoginCompletedMessage>(
                            this,
                            msg=> NavigationService.Navigate(
                                    new Uri("/_2HandApp;component/Views/Main.xaml",
                                    UriKind.Relative) );
    }
  ....
}

Вы можете видеть, что есть немногонемного больше (но простой) код в ViewModel и меньше в коде позади.Это также использовало преимущества DataBinding, которая лежит в основе MVVM.

Надеюсь, что это поможет:)

PS: класс LoginCompletedMessage в данном случае является просто пустым классом(используется только для определения типа сообщения), но вы можете использовать его для отправки дополнительной информации (возможно, вам все еще нужно отправить UserId)

1 голос
/ 15 мая 2011

Что ж, вы вызываете асинхронную версию логина WS.UserLoginAsync, что означает, что выполнение продолжается, и действительно, при проверке пользователя идентификатора пользователя нет.

Вы на самом деле не делаете MVVVM здесь, но в любом случае, давайте продолжим.Имейте событие в вашей «Viewmodel», которое вызывается, когда процесс входа в систему завершен (WS_UserLoginCompleted).Вы можете обработать его и вызвать навигацию в обработчике этого события.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...