За последние пару недель я работал над разработкой кросс-платформенного приложения (IOS / Android / WP7) с использованием структуры 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.
Код в 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? Спасибо!
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
s, но вы всегда можете сериализовать свои собственные объекты с помощью JSON.Net – или вы можете расширить структуру – это с открытым исходным кодом.
Обратите внимание, что в этом параметре передаются только string
s, int
s, double
s и bool
s – это связано с требованиями к сериализации для Xaml Urls и для Android Intents. Если вы хотите поэкспериментировать с навигацией, используя свои собственные сериализованные объекты, см. 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
в CreateViewModelFromIntent
в https://github.com/slodge/MvvmCross/blob/master/Cirrious/Cirrious.MvvmCross/Android/Views/MvxAndroidViewsContainer.cs )