2017-01-04 3 views
1

Я использую ViewModelLocator в своем проекте.Xamarin Forms доступ ко всем моделям просмотра

я BindingContent из ViewModelLocator в ResourceDictionary внутри app.xaml

Мои коды:

app.xaml

<?xml version="1.0" encoding="utf-8" ?> 
<Application xmlns="http://xamarin.com/schemas/2014/forms" 
      xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
      xmlns:controlsHelpers="clr-namespace:MyProj.Source.Helpers.UIHelper.ControlsHelpers;assembly=MyProj" 
      xmlns:configuration="clr-namespace:MyProj.Source.Configuration;assembly=MyProj" 
      x:Class="MyProj.App"> 
    <Application.Resources> 

    <ResourceDictionary> 
     <configuration:ViewModelLocator x:Key="ViewModelLocator"/> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

ViewModelLocator.cs

public class ViewModelLocator 
{ 
     public LoginViewModel LoginViewModel { get; set; } 
     public SignUpViewModel SignUpViewModel { get; set; } 


     public ViewModelLocator() 
     { 
      LoginViewModel = new LoginViewModel(); 
      SignUpViewModel = new SignUpViewModel(); 
     } 
} 

LoginViewModel.cs

public class LoginViewModel : AbstractViewModel 
{ 

     private MyModel UserData { get; set; } = new MyModel(); 


     private bool _isSignRequired; 


     public bool IsSignRequired 
     { 
      get { return _isSignRequired; } 
      set 
      { 
       if (value == _isSignRequired) return; 
       _isSignRequired = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string UserName 
     { 
      get { return UserData.UserName; } 
      set 
      { 
       if (value == UserData.UserName) return; 
       UserData.UserName = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string Password 
     { 
      get { return UserData.Password; } 
      set 
      { 
       if (value == UserData.Password) return; 
       UserData.Password = value; 
       OnPropertyChanged(); 
      } 
     } 

} 

SignUpViewModel.cs

public class SignUpViewModel : AbstractViewModel 
{  
     private string _checkUserResultImage; 

     public MyModel UserData { get; set; } = new MyModel(); 

     public string Phone 
     { 
      get { return UserData.Phone; } 
      set 
      { 
       if (UserData.Phone != null && value == UserData.Phone) return; 
       UserData.Phone = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string UserName 
     { 
      get { return UserData.UserName; } 
      set 
      { 
       if (UserData.UserName != null && value == UserData.UserName) return; 
       UserData.UserName = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string Password 
     { 
      get { return UserData.Password; } 
      set 
      { 
       if (UserData.Password != null && value == UserData.Password) return; 
       UserData.Password = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string Email 
     { 
      get { return UserData.Email; } 

      set 
      { 
       if (UserData.Email != null && value == UserData.Email) return; 
       UserData.Email = value; 
       OnPropertyChanged(); 
      } 
     } 

     public string CheckUserResultImage 
     { 
      get { return _checkUserResultImage; } 
      set 
      { 
       if (value == _checkUserResultImage) return; 
       _checkUserResultImage = value; 
        OnPropertyChanged(); 
      } 
     } 


     public Command SignUpCommand 
     { 
      get 
      { 
       return new Command(async() => 
       { 
        //Here I want to get data field from LoginViewModel 


       }); 
      } 
     } 
} 

Я хочу, чтобы получить данные из LoginViewModel в SignUpViewModel.

Как я могу это сделать?

+0

добавить код для SignUpViewModel –

+0

add LoginViewModel тоже. –

+0

@santoshkumar сделано – Atlantis

ответ

0

Я нашел решение для решения моего вопроса. Но я не уверен, что это хорошо.

Я добавил BindingContext к app.xaml

<Application.BindingContext> 
    <x:StaticResource Key="ViewModelLocator"/> 
    </Application.BindingContext> 

И я мог бы получить доступ к ViewModelLocator и LoginViewModel.

var model=Application.Current.BindingContext as ViewModelLocator; 
var login=model?.LoginViewModel.UserName; 

Это хорошая практика?

+0

, чтобы ответить на ваш вопрос - прочитайте ответ выше от PingZing –

3

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

Вы спрашиваете: «Как мне получить информацию из моего LoginViewModel в мою систему RegistrationViewModel?» Есть много разных способов сделать это! Многие из них, к сожалению, плохи и противоречат цели дизайна MVVM. MVVM поощряет развязку компонентов и инкапсуляцию.

Самый очевидный (и худший) способ сделать то, что вы хотите, - просто получить ссылку на LoginViewModel внутри RegistrationViewModel и напрямую обратиться к его свойствам. К сожалению, это очень хрупкое решение и обеспечивает жесткую зависимость от вашего LoginViewModel. Если ваш поток входа изменился, ваш аккаунт должен измениться с его помощью. Не идеально.

Итак, чтобы избежать жесткой связи ваших компонентов, вы хотите сделать что-то более простое: передайте только данные, которые вас интересуют. Есть много способов сделать это, например, события, передача параметров или система обмена сообщениями.

Мероприятия работают нормально, но я бы рекомендовал против них, так как это снова заставляет ваш механизм RegistrationViewModel напрямую зависеть от вашего LoginViewModel. Если с тобой все в порядке, это может сработать.

Передача параметров, вероятно, является самым легким решением, но, к сожалению, Xamarin Forms не поддерживает это из коробки. Я реализовал его раньше, но это связано с некоторой работой.

Система обмена сообщениями, которая позволяет вам подписываться и публиковать произвольные сообщения, является очень распространенным решением (и действительно, события на самом деле являются конкретной формой этого). Если вы ищете быстрое решение для вставки, я думаю, что это может быть вашим лучшим выбором, потому что MVVM Light Toolkit поставляется с Messenger, который делает именно это. Даже если вы не используете, что точное выполнение, хотя, в сущности, вы хотите сделать что-то вроде этого:

Допустим, ваш Посланник реализует некоторый интерфейс, который выглядит следующим образом:

public interface IMessenger 
{ 
    Publish<TMessage>(TMessage); 
    Subscribe<TMessage>(object, Action<TMessage>); //the object here should be a reference to the recipient. 
} 

А потом ваша реализация может выглядеть примерно так:

Вы бы использовать этот класс для передачи информации:

public class LoginMessageArgs 
{ 
    public string Username {get; private set;} 
    //whatever other information this message needs to contain...   
} 

Ваш LoginViewModel:

public class LoginViewModel : AbstractViewModel 
{ 
    //all your properties go here... 

    IMessenger messengerReference; 

    public LoginViewModel() 
    { 
     //Get a reference to your Messenger somehow. Maybe it's a singleton in ViewModelLocator? 
     messengerReference = ViewModelLocator.Messenger; 
    } 

    //Maybe you call this method when you navigate away from the LoginViewModel, or whenever it makes sense to send this information to your SignupViewModel. 
    private void PassLoginInformation() 
    { 
     messengerReference.Publish<LoginMessageArgs>(new LoginMessageArgs { Username = this.Username }); //etc 
    } 
} 

Ваш SignupViewModel:

public class SignUpViewModel : AbstractViewModel 
{ 

    //all your properties go here... 

    public SignupViewModel() 
    { 
     //Get a reference to your Messenger somehow. Maybe it's a singleton in ViewModelLocator? 
     IMessenger messengerReference = ViewModelLocator.Messenger; 
     messenger.Register<LoginMessageArgs>(this, OnLoginMessageReceived); 
    } 

    private OnLoginMessageReceived(LoginMessageArgs message) 
    { 
     //Do stuff with your message 
    } 
} 

Уф! Надеюсь, это поможет.

Смежные вопросы