最近在做 PCL(Portable Class Library)平台的項目,所以發一下自己遇到的問題
MvvmCross 是 PCL 平台的一個 MVVM 框架
地址:https://github.com/MvvmCross/MvvmCross
支持的平台:
- Silverlight for WP7, WP8
- Mono for Android (or Xamarin.Android)
- MonoTouch for iOS (or Xamarin.iOS)
- the WinRT XAML framework for Windows 8 Store apps.
- WPF
- Mono for Mac (or Xamarin.Mac)
在使用過程中首先遇到了彈出子窗體的問題,需要寫一個類繼承 MvxWpfViewPresenter
顯示子窗體時重寫 Present 方法
參考了一個列子:https://gist.github.com/cureos/6053471 ,還有朋友尚仔的大力幫助
關閉子窗體時, 再重寫 ChangePresentation 方法就可以了
在WPF項目中加入下邊代碼就可以了
代碼如下:
1 public class MvxWindowViewPresenter : MvxWpfViewPresenter 2 { 3 private readonly ContentControl _contentControl; 4 5 private FrameworkElement _frameworkElement; 6 public MvxWindowViewPresenter(ContentControl contentControl) 7 { 8 _contentControl = contentControl; 9 } 10 11 public override void Present(FrameworkElement frameworkElement) 12 { 13 _frameworkElement = frameworkElement; 14 var window = frameworkElement as Window; 15 if (window == null) 16 { 17 _contentControl.Content = frameworkElement; 18 } 19 else 20 { 21 window.Owner = _contentControl as Window; 22 window.ShowDialog(); 23 } 24 } 25 26 public override void ChangePresentation(MvxPresentationHint hint) 27 { 28 IMvxWpfView view; 29 var closeHint = hint as MvxClosePresentationHint; 30 if (closeHint != null 31 && (view = _frameworkElement as IMvxWpfView) != null 32 && ReferenceEquals(closeHint.ViewModelToClose, view.ViewModel)) 33 { 34 (_frameworkElement as Window).Close(); 35 } 36 37 base.ChangePresentation(hint); 38 } 39 }
寫一個子窗體繼承自 IMvxWpfView ,因為會監測這個接口
1 public class SubWindow: IMvxWpfView 2 { 3 private IMvxViewModel _viewModel; 4 5 public IMvxViewModel ViewModel 6 { 7 get { return _viewModel; } 8 set 9 { 10 _viewModel = value; 11 DataContext = value; 12 } 13 } 14 15 private int myVar; 16 17 public int MyProperty 18 { 19 get { return myVar; } 20 set { myVar = value; } 21 } 22 23 }
顯示子窗體:
1 ShowViewModel<SubViewModel>();
(SubViewModel為要顯示的子窗體的ViewModel)
關閉子窗體:
1 Close(this);
當需要傳參時,分為2種
一、從MainViewModel to SubViewModel
1 ShowViewModel<SubViewModel>(new { id= Id});
id 為子窗體中接受參數的名稱
Id 為主窗體中要傳遞的參數的名稱
同時子窗體中要寫一個接收參數的方法
1 public void Init(int Id) 2 { 3 Id= id; 4 }
這樣就把參數從MainViewModel 傳到了 SubViewModel
二、從SubViewModel to MainViewModel
這時就需要用到 MvvmCross 框架支持的插件 Plugins 中的 Messager
首先在 Core 項目中的 App.cs 中重寫一個方法,把插件注冊進來
1 public override void LoadPlugins(IMvxPluginManager pluginManager) 2 { 3 base.LoadPlugins(pluginManager); 4 5 if (pluginManager == null) 6 { 7 return; 8 } 9 10 pluginManager.EnsurePluginLoaded<PluginLoader>(); 11 }
其次寫一個 Message 繼承 MvxMessage
1 public class XXXMessage : MvxMessage 2 { 3 public XXXMessage(object sender, int id) 4 : base(sender) 5 { 6 Id= id; 7 } 8 9 public int Id{ get; private set; } 10 }
再在 MainViewModel 中聲明一個字段,並在構造中實例化Messager
1 private readonly MvxSubscriptionToken _token; 2 3 public MainViewModel() 4 { 5 var messenger = Mvx.Resolve<IMvxMessenger>(); 6 _token = messenger.Subscribe<XXXMessage>(OnXXXMessage); 7 } 8 9 private void OnXXXMessage(XXXMessage XXXMessage) 10 { 11 if (XXXMessage == null) 12 { 13 return; 14 } 15 // TODO 16 }
最后在 SubViewModel 中需要回傳參數的地方把參數傳回來
1 var messenger = Mvx.Resolve<IMvxMessenger>(); 2 messenger.Publish<XXXMessage>(new XXXMessagethis, id));
如此就可以在MvvmCross 中就可以顯示子窗體、關閉子窗體、ViewModel 之間互相傳參
Tips:據說 Service 和 Settings 也可以回傳參數,有做出來的歡迎發來分享!