2012-04-17 6 views
7

За последние пару недель я работал над разработкой кросс-платформенного приложения (IOS/Android/WP7) с использованием структуры MVVMCross. Сегодня я столкнулся с проблемой, я действительно не знаю, как ее решить, поэтому, надеюсь, вы можете подтолкнуть меня в правильном направлении.Передача переменных из ViewModel в другой View (MVVMCross)

В IOS я следующее построение для навигации на другую страницу (код ниже расположен в ViewModel):

KeyValuePair<string,string> kvpAct1 = new KeyValuePair<string, string>("short", ".countertest5"); 

public IMvxCommand BeckhoffActuator1 
{ 
    get 
    {   
     return new MvxRelayCommand<Type>((type) => this.RequestNavigate<Beckhoff.BeckhoffActuatorViewModel>(kvpAct1)); 
    } 
} 

Когда IMvxCommand обжигают (кнопка нажата) следующий вид загрузки, в этом случае BeckhoffActuatorViewModel. В коде BeckhoffActuatorView я использую KeyValuePair сверху:

public class BeckhoffActuatorView : MvxTouchDialogViewController<BeckhoffActuatorViewModel> 
{ 

    ICollection<string> icol; 

    public BeckhoffActuatorView(MvxShowViewModelRequest request) : base(request, UITableViewStyle.Grouped, null, true) 
    { 

     icol = request.ParameterValues.Values; 

    } 

    public override void ViewDidLoad() 
    { 
     //Code 
    } 
} 

Эта конструкция работает отлично в IOS, но я хотел бы использовать ту же конструкцию в моем Android App.

Код в ViewModel не изменился, так как это идея MVVM. Но код BackhoffActuatorView отличается для Android:

public class BeckhoffActuatorView : MvxBindingActivityView<BeckhoffSensorViewModel> 
{ 
    public ICollection<string> icol; 

    public BeckhoffActuatorView() 
    { 
     Debug.WriteLine("Standard"); 
    } 

    public BeckhoffActuatorView(MvxShowViewModelRequest request) 
    { 
     Debug.WriteLine("Custom"); 

     icol = request.ParameterValues.Values; 
    } 

    protected override void OnViewModelSet() 
    { 

     SetContentView(Resource.Layout.BeckhoffActuatorView); 

    } 
} 

Код выше не работает, MvxBindingActivityView не кажется, реализовать что-то подобное ViewController я использую в IOS. Код входит только в стандартный конструктор, и когда я оставляю его полностью, он не будет компилироваться/запускаться.

Кто-нибудь знает, что я могу получить доступ к keyvaluepair, который я отправляю с RequestNavigate? Спасибо!

ответ

10

MVVMCross очень основан на конвенции, и он работает над идеей передачи сообщений между ViewModels, где это возможно.

Если перейти к ViewModel с помощью:

KeyValuePair<string,string> kvpAct1 = new KeyValuePair<string, string>("short", ".countertest5"); 

public IMvxCommand BeckhoffActuator1 
{ 
    get 
    {   
     return new MvxRelayCommand<Type>((type) => this.RequestNavigate<Beckhoff.BeckhoffActuatorViewModel>(kvpAct1)); 
    } 
} 

, то вы должны быть в состоянии выбрать, что в BeckhoffActuatorViewModel с помощью конструктора:

public class BeckhoffActuatorViewModel : MvxViewModel 
{ 
    public BeckhoffActuatorViewModel(string short) 
    { 
     ShortValue = short; 
    } 

    private string _shortValue; 
    public string ShortValue 
    { 
     get 
     { 
      return _shortValue; 
     } 
     set 
     { 
      _shortValue = value; 
      FirePropertyChanged("ShortValue"); 
     } 
    } 
} 

И ваши взгляды могут получить доступ к ViewModel.ShortValue (для iOS это можно сделать после base.ViewDidLoad(), для Android после OnCreate() и для WP7 после OnNavigatedTo)

Для примера это, взгляните на пример TwitterSearch:

Это имеет HomeViewModel, который вызывает навигация с помощью:

private void DoSearch() 
    { 
     RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText }); 
    } 

и TwitterViewModel, который принимает SEARCHTERM с помощью конструктора:

public TwitterViewModel(string searchTerm) 
    { 
     StartSearch(searchTerm); 
    } 

Обратите внимание, что в настоящее время в этом сообщении разрешено использовать только string с, но вы всегда можете сериализовать свои собственные объекты с помощью JSON.Net - или вы можете расширить структуру - это с открытым исходным кодом.

Пожалуйста, обратите внимание, что только string s, int s, double s и s bool разрешены в этом параметре конструктора, проходящем в настоящее время - это связанно с требованиями сериализаций для Xaml URLS и для Android намерений. Если вы хотите поэкспериментировать с навигацией, используя свои собственные сериализованные объекты, пожалуйста, см. http://slodge.blogspot.co.uk/2013/01/navigating-between-viewmodels-by-more.html.

Кроме того, обратите внимание, что если вы хотите использовать анонимный объект навигации (RequestNavigate<TwitterViewModel>(new { searchTerm = SearchText });), то вам нужно будет, чтобы убедиться, что атрибут InternalsVisibleTo установлен - см https://github.com/slodge/MvvmCrossTwitterSearch/blob/master/TwitterSearch.Core/Properties/AssemblyInfo.cs:

[assembly: InternalsVisibleTo("Cirrious.MvvmCross")] 

Далее .. не для слабонервных ... и это не «хороший код mvvm» ... но если вам действительно нужно/нужно получить доступ к данным MvxShowViewModelRequest в активности Android, вы можете извлечь его из входящего Intent - есть строка Extras, содержащая запрос (см. десериализацию в CreateViewModelFromIntent в https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Views/MvxAndroidViewsContainer.cs)

+4

Спасибо, Стюарт, используя пример Twitter, мне удалось исправить мою проблему! – David

+0

Хорошая работа - если вам нужен еще один пример передачи параметров, вы можете попробовать образцы CustomerManagement и Books. :) – Stuart