Логин модала с шаблона MVVM


Я хотел бы некоторую обратную связь о том, Это следует принципы в MVVM.

Файл MainPage есть кнопка входа, которая открывает модальное страницу входа. После успешного входа в LoginPageViewModel будет вызывать событие, которое обрабатывается в родительской модели представления.

Я использую Action объектов Показать/Скрыть модальные глаголы. Действия определяются в отделенного кода страницы и ссылаться на его ViewModel.

MainPage.xaml

<Button Command="{Binding ShowLoginModalCommand}" Text="Login"/>

MainPage.xaml.cs

public MainPage()
{
    var vm = new MainPageViewModel();
    vm.ShowLoginModal += (lvm) => Navigation.PushModalAsync(new LoginPage(lvm));
    vm.HideLoginModal += () => Navigation.PopModalAsync();
    BindingContext = vm;
    InitializeComponent();
}

MainViewModel.cs

public Action<LoginViewModel> ShowLoginModal;
public Action HideLoginModal;

public ICommand ShowLoginModalCommand => new Command(() =>
{
    var lvm = new LoginViewModel();

    lvm.LoginSucceeded += (se, ev) =>
    {
        this.Customer = ev.Customer;
        HideLoginModal();
    };

    ShowLoginModal(lvm);
}

public Customer Customer
{
    get => _customer;
    set
    {
        _customer = value;
        OnPropertyChanged(nameof(Customer));
    }
}

LoginPage.xaml

<Button Command="{Binding LoginCommand}" Text="Login"/>

LoginViewModel.cs

public ICommand LoginCommand => new Command(async () => 
{
    var customer = await VerifyLogin(); // Assume valid login.
    LoginSucceeded(this, new LoginSuccessEventArgs(customer));
}

public class LoginSuccessEventArgs : EventArgs
{
    public Customer Customer { get; set; }
    public LoginSuccessEventArgs(Customer customer) => Customer = customer;
}
public event EventHandler<LoginSuccessEventArgs> LoginSucceeded;


1251
1
задан 3 апреля 2018 в 05:04 Источник Поделиться
Комментарии
1 ответ

Вообще говоря, я считаю хорошая реализация и нравится простота подхода. Я бы отметил некоторые проблемы, я хоть и нашли.

Непоследовательный стиль в MVVM

Вы используете два разных способа, чтобы инстанцировать вид и viewModels и связав их вместе в обоих взглядов, непоследовательность, которые могли бы сделать больше и скандальнее, тем более сложные программы.

В MainPage вы создаете ViewModel в View конструктор, и его назначения BindingContext сразу. Но в LoginPage создать ViewModel в обработчике главной страницы и передать его в конструктор вид (не показано здесь, но я предполагаю, что это также назначает BindingContext С ним).

Специально для больших приложений, важно четко определить один стиль, либо вид на первый или первая модель представления, и жить с ней (я даже не знаю, если это называется "стиль", но похоже, что для меня). Подробнее о Проблема в том, что когда ВМ начинают принимать зависимости от Услуги и другие вещи, вы, скорее всего, захотят использовать МОК контейнер за их внедрение, и затем это становится более важно четко определить, кто будет создавать просмотр моделей и как. Лично мне нравится модель представления-первый подход, в котором просмотр моделей создать другими моделями представлений и передаются на вид.

MainPage С ViewModel


  • Почему ShowLoginModal и HideLoginModal равнине открытых полей? В подобных ситуациях, я бы ожидать, что они будут нормальные акции, вырученные от ViewModel и обрабатываются в виде. Таким образом, чувствует себя немного нестандартные.

  • На ShowLoginModalCommand метод в ViewModel создается логин с ViewModel непосредственно. Возможно, ненужных сейчас, но подумайте об использовании IoC-контейнер или другая фабрика для создания этого, как обычно, когда другими моделями представлений занять дополнительное зависимостей становится все труднее создавать их всех в узде.

  • В Customer сеттер не должен быть государственным, частным и одного. Вы только хотите установить текущего пользователя с логином и нигде больше, так что кристально чистой.

  • На вызовы ShowLoginModal и HideLoginModal делегаты не содержать null-проверка, и в результате NullReferenceException если никто не suscribed к ним. Хороший ярлык для вызова их безопасно использовать ShowLoginModal?(lvm); синтаксис.

LoginPage С ViewModel


  • Остерегайтесь асинхронного повторного входа в LoginCommand метод. В VerifyLogin звонок внутри он может быть медленным, но так как это await вызова, пользовательский интерфейс остается отзывчивым. Это означает, что пользователь может делать другие вещи в то же время, в том числе изменение пользователя/пароль или даже снова нажмите кнопку "Вход"! Что может иметь множество непредвиденных последствий. Я бы его при отключении пользовательского интерфейса, в то время как проходит проверка, используя что-то вроде этого в виртуальной машине:

    public bool EnableForm { get; set; }<br>
    public ICommand LoginCommand => new Command(async () =>
    {
    //Disable UI before doing anything
    EnableForm = false;
    OnPropertyChanged(nameof(EnableForm));
    var customer = await VerifyLogin(); // Assume valid login.
    LoginSucceeded(this, new LoginSuccessEventArgs(customer));
    }

    И в Мнение, связывать элементы управления на это имущество:
    <Button Command="{Binding LoginCommand}" Text="Login" IsEnabled="{Binding EnableForm}"/>

  • В LoginSuccessEventArgs в Customer собственность не нужно читать-писать. Еще раз повторюсь, так как ты просто информируя значение, нет смысла менять его после создания. Кроме того, конструктор должен проверить на null на переданном заказчиком.

  • Возможно, это не показано здесь, или просто незавершенное дело, но нет обработки при ошибке входа в систему дело, что надо просто снова включить контроль (после моего внушения сверху), показать некоторые сообщения об ошибке пользователю и не поднимать LoginSuccess событие.

  • Как на главной странице, поднятие событие не является нулем проверены и будут взрывать, если никто не бывает suscribed.

  • Вызов VerifyLogin способ, хотя, возможно, упрощенный здесь, может означать много работы под прикрытием. Это такая штука, которую лучше делегировать на службу, чтобы сделать всю тяжелую работу, и просто уровень представления ручка визуальная вещь. Я бы впрыскивают его в конструкторе и назовите его прохождения пользователя/пароль ввел, и он вернется успеха или неудачи. Что-то вроде этого:

    private readonly ILoginService _loginService;<br/>
    public LoginViewModel(ILoginService loginService)
    {
    if(loginService == null) throw new ArgumentNullException(nameof(loginService));<br/>
    _loginService = loginService;
    }<br/>
    public ICommand LoginCommand => new Command(async () =>
    {
    var customer = await _loginService.VerifyLogin(Username, Password);
    if(customer == null)
    //show some error message here
    else
    LoginSucceeded(this, new LoginSuccessEventArgs(customer));
    }

1
ответ дан 5 апреля 2018 в 02:04 Источник Поделиться