MvvmCross for WPF 支持子窗体显示、关闭、传参
最近在做 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 也可以回传参数,有做出来的欢迎发来分享!