PageRenderTime 5ms CodeModel.GetById 14ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 1ms

/MVVMSidekick/MVVMSidekick.Shared/Views.cs

https://github.com/zoujuny/MVVM-Sidekick
C# | 1899 lines | 1308 code | 460 blank | 131 comment | 139 complexity | ce3f16a370eb484ac5acbbe4718a83f2 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1using System;
   2using System.Collections.Generic;
   3using System.Linq;
   4using System.Text;
   5using System.ComponentModel;
   6using System.Linq.Expressions;
   7using System.Runtime.Serialization;
   8using System.Reflection;
   9using System.Threading.Tasks;
  10using System.Threading;
  11using System.Windows.Input;
  12using MVVMSidekick.ViewModels;
  13using MVVMSidekick.Commands;
  14using System.Runtime.CompilerServices;
  15using MVVMSidekick.Reactive;
  16using System.Reactive.Linq;
  17using System.Reactive.Subjects;
  18using System.Reactive;
  19using MVVMSidekick.EventRouting;
  20using System.Collections.ObjectModel;
  21using System.Collections.Specialized;
  22using System.IO;
  23using System.Collections;
  24using System.Windows;
  25
  26
  27
  28#if NETFX_CORE
  29using Windows.UI.Xaml;
  30using Windows.UI.Xaml.Data;
  31using Windows.UI.Xaml.Controls;
  32using System.Collections.Concurrent;
  33using Windows.UI.Xaml.Navigation;
  34
  35using Windows.UI.Xaml.Controls.Primitives;
  36
  37#elif WPF
  38using System.Windows.Controls;
  39
  40
  41using System.Collections.Concurrent;
  42using System.Windows.Navigation;
  43
  44using MVVMSidekick.Views;
  45using System.Windows.Controls.Primitives;
  46using MVVMSidekick.Utilities;
  47
  48#elif SILVERLIGHT_5||SILVERLIGHT_4
  49using System.Windows;
  50using System.Windows.Controls;
  51using System.Windows.Data;
  52using System.Windows.Navigation;
  53using System.Windows.Controls.Primitives;
  54#elif WINDOWS_PHONE_8||WINDOWS_PHONE_7
  55using System.Windows;
  56using System.Windows.Controls;
  57using Microsoft.Phone.Controls;
  58using System.Windows.Data;
  59using System.Windows.Navigation;
  60using System.Windows.Controls.Primitives;
  61#endif
  62
  63#if (! WPF) && (! NETFX_CORE)
  64namespace System.Windows
  65{
  66
  67
  68
  69}
  70
  71
  72
  73#endif
  74
  75namespace MVVMSidekick
  76{
  77
  78	namespace Views
  79	{
  80
  81
  82		public static class ViewHelper
  83		{
  84			public static readonly string DEFAULT_VM_NAME = "DesignVM";
  85			public static object GetDefaultDesigningViewModel(this IView view)
  86			{
  87				var f = view as FrameworkElement;
  88				object rval = null;
  89#if NETFX_CORE
  90				if (!f.Resources.ContainsKey(DEFAULT_VM_NAME))
  91#else
  92				if (!f.Resources.Contains(DEFAULT_VM_NAME))
  93#endif
  94				{
  95					return null;
  96				}
  97				else
  98				{
  99					rval = f.Resources[DEFAULT_VM_NAME];
 100				}
 101				return rval;
 102			}
 103
 104			internal static RoutedEventHandler ViewUnloadCallBack
 105				= async (o, e) =>
 106				{
 107					IView v = o as IView;
 108					if (v != null)
 109					{
 110						var m = v.ViewModel as IViewModelLifetime;
 111						if (m != null)
 112						{
 113							await m.OnBindedViewUnload(v);
 114						}
 115					}
 116				};
 117			internal static PropertyChangedCallback DesigningViewModelChangedCallBack
 118				= (o, e) =>
 119					  {
 120						  var oiview = o as IView;
 121						  if (Utilities.Runtime.IsInDesignMode)
 122						  {
 123							  oiview.ViewModel = e.NewValue as IViewModel;
 124						  }
 125					  };
 126
 127
 128
 129			internal static PropertyChangedCallback ViewModelChangedCallback
 130				= (o, e) =>
 131				{
 132					dynamic item = o;
 133					var oiview = o as IView;
 134					var fele = (oiview.ContentObject as FrameworkElement);
 135					if (fele==null)
 136					{
 137						return;
 138					}
 139					if (object.ReferenceEquals(fele.DataContext, e.NewValue))
 140					{
 141						return;
 142					}
 143					(oiview.ContentObject as FrameworkElement).DataContext = e.NewValue;
 144					var nv = e.NewValue as IViewModel;
 145					var ov = e.OldValue as IViewModel;
 146					if (ov != null)
 147					{
 148						ov.OnUnbindedFromView(oiview, nv);
 149					}
 150					if (nv != null)
 151					{
 152						nv.OnBindedToView(oiview, ov);
 153					}
 154
 155				};
 156
 157			internal static FrameworkElement GetContentAndCreateIfNull(this IView control)
 158			{
 159				var c = (control.ContentObject as FrameworkElement);
 160				if (c == null)
 161				{
 162					control.ContentObject = c = new Grid();
 163				}
 164				return c;
 165			}
 166
 167			public static void SelfClose(this IView view)
 168			{
 169				view.ViewModel = null;
 170				if (view is UserControl || view is Page)
 171				{
 172					var viewElement = view as FrameworkElement;
 173					var parent = viewElement.Parent;
 174					if (parent is Panel)
 175					{
 176						(parent as Panel).Children.Remove(viewElement);
 177					}
 178					else if (parent is Frame)
 179					{
 180						var f = (parent as Frame);
 181						if (f.CanGoBack)
 182						{
 183							f.GoBack();
 184						}
 185						else
 186						{
 187							f.Content = null;
 188						}
 189					}
 190					else if (parent is ContentControl)
 191					{
 192						(parent as ContentControl).Content = null;
 193					}
 194					else if (parent is Page)
 195					{
 196						(parent as Page).Content = null;
 197					}
 198					else if (parent is UserControl)
 199					{
 200						(parent as UserControl).Content = null;
 201					}
 202
 203				}
 204#if WPF
 205				else if (view is Window)
 206				{
 207					(view as Window).Close();
 208				}
 209#endif
 210
 211
 212			}
 213
 214		}
 215
 216#if WPF
 217		public class MVVMWindow : Window, IView
 218		{
 219
 220			public MVVMWindow()
 221				: this(null)
 222			{
 223			}
 224
 225
 226			public MVVMWindow(IViewModel viewModel)
 227			{
 228
 229				Unloaded += ViewHelper.ViewUnloadCallBack;
 230				Loaded += async (_1, _2) =>
 231				{
 232
 233					//    if (viewModel != null)
 234					//    {
 235					//        //   this.Resources[ViewHelper.DEFAULT_VM_NAME] = viewModel;
 236					//        if (!object.ReferenceEquals(ViewModel, viewModel))
 237					//        {
 238					//            ViewModel = viewModel;
 239					//        }
 240					//    }
 241					//    else
 242					//    {
 243					//        var solveV = this.GetDefaultViewModel();
 244					//        if (solveV != null)
 245					//        {
 246					//            ViewModel = solveV;
 247					//        }
 248
 249					//    }
 250					//    ////ViewModel = ViewModel ?? new DefaultViewModel();
 251
 252					await ViewModel.OnBindedViewLoad(this);
 253				};
 254			}
 255
 256			public object ContentObject
 257			{
 258				get
 259				{
 260					return Content;
 261				}
 262				set
 263				{
 264					Content = value;
 265				}
 266			}
 267
 268
 269
 270
 271			//public IViewModel DesigningViewModel
 272			//{
 273			//	get { return (IViewModel)GetValue(DesigningViewModelProperty); }
 274			//	set { SetValue(DesigningViewModelProperty, value); }
 275			//}
 276
 277			//// Using a DependencyProperty as the backing store for DesigningViewModel.  This enables animation, styling, binding, etc...
 278			//public static readonly DependencyProperty DesigningViewModelProperty =
 279			//	DependencyProperty.Register("DesigningViewModel", typeof(IViewModel), typeof(MVVMWindow), new PropertyMetadata(null, ViewHelper.DesigningViewModelChangedCallBack));
 280
 281
 282
 283			public IViewModel ViewModel
 284			{
 285				get
 286				{
 287					var rval = GetValue(ViewModelProperty) as IViewModel;
 288					var c = this.GetContentAndCreateIfNull();
 289					if (rval == null)
 290					{
 291
 292						rval = c.DataContext as IViewModel;
 293						SetValue(ViewModelProperty, rval);
 294
 295					}
 296					else
 297					{
 298
 299						if (!Object.ReferenceEquals(c.DataContext, rval))
 300						{
 301							c.DataContext = rval;
 302						}
 303					}
 304					return rval;
 305				}
 306				set
 307				{
 308					SetValue(ViewModelProperty, value);
 309					var c = this.GetContentAndCreateIfNull();
 310					if (!Object.ReferenceEquals(c.DataContext, value))
 311					{
 312						c.DataContext = value;
 313					}
 314
 315				}
 316			}
 317
 318
 319
 320			// Using a DependencyProperty as the backing store for ViewModel.  This enables animation, styling, binding, etc...
 321			public static readonly DependencyProperty ViewModelProperty =
 322				DependencyProperty.Register("ViewModel", typeof(IViewModel), typeof(MVVMWindow), new PropertyMetadata(null, ViewHelper.ViewModelChangedCallback));
 323
 324
 325			public ViewType ViewType
 326			{
 327				get { return ViewType.Window; }
 328			}
 329
 330
 331
 332
 333		}
 334
 335
 336
 337
 338#endif
 339
 340#if WINDOWS_PHONE_7||WINDOWS_PHONE_8
 341        public partial class MVVMPage : PhoneApplicationPage, IView
 342#else
 343		public class MVVMPage : Page, IView
 344#endif
 345		{
 346
 347
 348
 349			public MVVMPage()
 350				: this(null)
 351			{
 352
 353			}
 354
 355
 356
 357#if WPF
 358
 359
 360			public Frame Frame
 361			{
 362				get { return (Frame)GetValue(FrameProperty); }
 363				set { SetValue(FrameProperty, value); }
 364			}
 365
 366			// Using a DependencyProperty as the backing store for Frame.  This enables animation, styling, binding, etc...
 367			public static readonly DependencyProperty FrameProperty =
 368				DependencyProperty.Register("Frame", typeof(Frame), typeof(MVVMPage), new PropertyMetadata(null));
 369
 370
 371			DependencyObject IView.Parent
 372			{
 373				get
 374				{
 375					return Frame;
 376
 377				}
 378			}
 379#endif
 380
 381			public MVVMPage(IViewModel viewModel)
 382			{
 383				ViewModel = viewModel;
 384				Unloaded += ViewHelper.ViewUnloadCallBack;
 385#if WPF
 386				Loaded += async (o, e) =>
 387					{
 388						await ViewModel.OnBindedViewLoad(this);
 389
 390					};
 391#endif
 392
 393			}
 394
 395
 396
 397
 398#if ! WPF
 399			//WPF Pages' Content are objects but others are FE .
 400			public object ContentObject
 401			{
 402				get { return Content; }
 403				set { Content = value as FrameworkElement; }
 404
 405			}
 406
 407			bool IsLoaded = false;
 408
 409			//WPF navigates page instances but other navgates with parameters
 410			protected override void OnNavigatedTo(NavigationEventArgs e)
 411			{
 412
 413				base.OnNavigatedTo(e);
 414				RoutedEventHandler loadEvent = null;
 415
 416				loadEvent = async (_1, _2) =>
 417				{
 418
 419
 420					EventRouting.EventRouter.Instance.RaiseEvent(this, e);
 421
 422					if (ViewModel != null)
 423					{
 424						await ViewModel.OnBindedViewLoad(this);
 425					}
 426
 427					IsLoaded = true;
 428					this.Loaded -= loadEvent;
 429
 430
 431
 432
 433
 434				};
 435				this.Loaded += loadEvent;
 436
 437			}
 438
 439
 440
 441
 442			protected override void OnNavigatedFrom(NavigationEventArgs e)
 443			{
 444				base.OnNavigatedFrom(e);
 445
 446#if SILVERLIGHT_5
 447                if (ViewModel.StageManager.DefaultStage.NavigateRequestContexts.ContainsKey(e.Uri.ToString()))
 448#else
 449				if (e.NavigationMode == NavigationMode.Back)
 450#endif
 451
 452				{
 453
 454					if (ViewModel != null)
 455					{
 456
 457						ViewModel.Dispose();
 458					}
 459
 460
 461				}
 462
 463			}
 464#else
 465			public object ContentObject
 466			{
 467				get
 468				{
 469					return Content;
 470				}
 471				set
 472				{
 473					Content = value;
 474				}
 475			}
 476#endif
 477
 478
 479
 480			//public IViewModel DesigningViewModel
 481			//{
 482			//	get { return (IViewModel)GetValue(DesigningViewModelProperty); }
 483			//	set { SetValue(DesigningViewModelProperty, value); }
 484			//}
 485
 486			//// Using a DependencyProperty as the backing store for DesigningViewModel.  This enables animation, styling, binding, etc...
 487			//public static readonly DependencyProperty DesigningViewModelProperty =
 488			//	DependencyProperty.Register("DesigningViewModel", typeof(IViewModel), typeof(MVVMPage), new PropertyMetadata(null, ViewHelper.DesigningViewModelChangedCallBack));
 489
 490
 491			public IViewModel ViewModel
 492			{
 493				get
 494				{
 495					var rval = GetValue(ViewModelProperty) as IViewModel;
 496					var c = this.GetContentAndCreateIfNull();
 497					if (rval == null)
 498					{
 499
 500						rval = c.DataContext as IViewModel;
 501						SetValue(ViewModelProperty, rval);
 502
 503					}
 504					else
 505					{
 506
 507						if (!Object.ReferenceEquals(c.DataContext, rval))
 508						{
 509							c.DataContext = rval;
 510						}
 511					}
 512					return rval;
 513				}
 514				set
 515				{
 516
 517					SetValue(ViewModelProperty, value);
 518					var c = this.GetContentAndCreateIfNull();
 519					if (!Object.ReferenceEquals(c.DataContext, value))
 520					{
 521						c.DataContext = value;
 522					}
 523
 524				}
 525			}
 526
 527			// Using a DependencyProperty as the backing store for ViewModel.  This enables animation, styling, binding, etc...
 528			public static readonly DependencyProperty ViewModelProperty =
 529				DependencyProperty.Register("ViewModel", typeof(IViewModel), typeof(MVVMPage), new PropertyMetadata(null,
 530					(o, e) =>
 531					{
 532						var p = o as MVVMPage;
 533#if !WPF
 534						if (p.IsLoaded)
 535						{
 536							ViewHelper.ViewModelChangedCallback(o, e);
 537						}
 538#else
 539						ViewHelper.ViewModelChangedCallback(o, e);
 540#endif
 541					}
 542
 543					));
 544
 545
 546#if NETFX_CORE
 547
 548			/// <summary>
 549			/// Populates the page with content passed during navigation.  Any saved state is also
 550			/// provided when recreating a page from a prior session.
 551			/// </summary>
 552			/// <param name="navigationParameter">The parameter value passed to
 553			/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
 554			/// </param>
 555			/// <param name="pageState">A dictionary of state preserved by this page during an earlier
 556			/// session.  This will be null the first time a page is visited.</param>
 557			protected virtual void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
 558			{
 559				if (ViewModel != null)
 560				{
 561					ViewModel.LoadState(navigationParameter, pageState);
 562				}
 563			}
 564
 565			/// <summary>
 566			/// Preserves state associated with this page in case the application is suspended or the
 567			/// page is discarded from the navigation cache.  Values must conform to the serialization
 568			/// requirements of <see cref="SuspensionManager.SessionState"/>.
 569			/// </summary>
 570			/// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
 571			protected virtual void SaveState(Dictionary<String, Object> pageState)
 572			{
 573				if (ViewModel != null)
 574				{
 575					ViewModel.SaveState(pageState);
 576
 577				}
 578			}
 579#endif
 580
 581
 582			public ViewType ViewType
 583			{
 584				get { return ViewType.Page; }
 585			}
 586
 587			public void Dispose()
 588			{
 589
 590				this.SelfClose();
 591
 592
 593			}
 594
 595
 596
 597		}
 598
 599
 600
 601		public class MVVMControl : UserControl, IView
 602		{
 603
 604			public MVVMControl()
 605				: this(null)
 606			{
 607
 608			}
 609
 610
 611			public MVVMControl(IViewModel viewModel)
 612			{
 613
 614				Unloaded += ViewHelper.ViewUnloadCallBack;
 615				////////// Unloaded += (_1, _2) => ViewModel = null;
 616				Loaded += async (_1, _2) =>
 617				{
 618
 619					//if (viewModel != null)
 620					//{
 621					//    //this.Resources[ViewHelper.DEFAULT_VM_NAME] = viewModel;
 622					//    if (!object.ReferenceEquals(ViewModel, viewModel))
 623					//    {
 624					//        ViewModel = viewModel;
 625
 626					//    }
 627					//}
 628					//else
 629					//{
 630					//    var solveV = this.GetDefaultViewModel();
 631					//    if (solveV != null)
 632					//    {
 633					//        ViewModel = solveV;
 634					//    }
 635
 636					//}
 637					//ViewModel = ViewModel ?? new DefaultViewModel();
 638
 639
 640					await ViewModel.OnBindedViewLoad(this);
 641				};
 642			}
 643#if !WPF
 644			public object ContentObject
 645			{
 646				get { return Content; }
 647				set { Content = value as FrameworkElement; }
 648
 649			}
 650#else
 651			public object ContentObject
 652			{
 653				get
 654				{
 655					return Content;
 656				}
 657				set
 658				{
 659					Content = value;
 660				}
 661			}
 662#endif
 663#if NETFX_CORE
 664
 665			/// <summary>
 666			/// Populates the page with content passed during navigation.  Any saved state is also
 667			/// provided when recreating a page from a prior session.
 668			/// </summary>
 669			/// <param name="navigationParameter">The parameter value passed to
 670			/// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
 671			/// </param>
 672			/// <param name="pageState">A dictionary of state preserved by this page during an earlier
 673			/// session.  This will be null the first time a page is visited.</param>
 674			protected virtual void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
 675			{
 676				if (ViewModel != null)
 677				{
 678					ViewModel.LoadState(navigationParameter, pageState);
 679				}
 680			}
 681
 682			/// <summary>
 683			/// Preserves state associated with this page in case the application is suspended or the
 684			/// page is discarded from the navigation cache.  Values must conform to the serialization
 685			/// requirements of <see cref="SuspensionManager.SessionState"/>.
 686			/// </summary>
 687			/// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
 688			protected virtual void SaveState(Dictionary<String, Object> pageState)
 689			{
 690				if (ViewModel != null)
 691				{
 692					ViewModel.SaveState(pageState);
 693				}
 694			}
 695#endif
 696
 697			//public IViewModel DesigningViewModel
 698			//{
 699			//	get { return (IViewModel)GetValue(DesigningViewModelProperty); }
 700			//	set { SetValue(DesigningViewModelProperty, value); }
 701			//}
 702
 703			//// Using a DependencyProperty as the backing store for DesigningViewModel.  This enables animation, styling, binding, etc...
 704			//public static readonly DependencyProperty DesigningViewModelProperty =
 705			//	DependencyProperty.Register("DesigningViewModel", typeof(IViewModel), typeof(MVVMControl), new PropertyMetadata(null, ViewHelper.DesigningViewModelChangedCallBack));
 706			public IViewModel ViewModel
 707			{
 708				get
 709				{
 710					var vm = GetValue(ViewModelProperty) as IViewModel;
 711					var content = this.GetContentAndCreateIfNull();
 712					if (vm == null)
 713					{
 714
 715						vm = content.DataContext as IViewModel;
 716						SetValue(ViewModelProperty, vm);
 717
 718					}
 719					else
 720					{
 721						IView view = this;
 722
 723
 724						if (!Object.ReferenceEquals(content.DataContext, vm))
 725						{
 726
 727							content.DataContext = vm;
 728						}
 729					}
 730					return vm;
 731				}
 732				set
 733				{
 734					SetValue(ViewModelProperty, value);
 735					var c = this.GetContentAndCreateIfNull();
 736					if (!Object.ReferenceEquals(c.DataContext, value))
 737					{
 738						c.DataContext = value;
 739					}
 740
 741				}
 742			}
 743
 744			// Using a DependencyProperty as the backing store for ViewModel.  This enables animation, styling, binding, etc...
 745			public static readonly DependencyProperty ViewModelProperty =
 746				DependencyProperty.Register("ViewModel", typeof(IViewModel), typeof(MVVMControl), new PropertyMetadata(null, ViewHelper.ViewModelChangedCallback));
 747
 748
 749			public ViewType ViewType
 750			{
 751				get { return ViewType.Control; }
 752			}
 753
 754		}
 755		public enum ViewType
 756		{
 757			Page,
 758			Window,
 759			Control
 760		}
 761
 762		public interface IView
 763		{
 764			IViewModel ViewModel { get; set; }
 765
 766			ViewType ViewType { get; }
 767
 768			Object ContentObject { get; set; }
 769
 770			DependencyObject Parent { get; }
 771
 772		}
 773
 774
 775		public interface IView<TViewModel> : IView, IDisposable where TViewModel : IViewModel
 776		{
 777			TViewModel SpecificTypedViewModel { get; set; }
 778		}
 779
 780		public struct ViewModelToViewMapper<TModel>
 781			where TModel : IViewModel
 782		{
 783
 784			public static void MapViewToViewModel<TView>()
 785			{
 786				Func<IViewModel> func;
 787				if (!ViewModelToViewMapperHelper.ViewToVMMapping.TryGetValue(typeof(TView), out func))
 788				{
 789					ViewModelToViewMapperHelper.ViewToVMMapping.Add(typeof(TView), () => (ViewModelLocator<TModel>.Instance.Resolve()));
 790				}
 791
 792
 793			}
 794#if WPF
 795			public ViewModelToViewMapper<TModel> MapToDefault<TView>(TView instance) where TView : class,IView
 796			{
 797				MapViewToViewModel<TView>();
 798				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(instance);
 799				return this;
 800			}
 801
 802			public ViewModelToViewMapper<TModel> MapTo<TView>(string viewMappingKey, TView instance) where TView : class,IView
 803			{
 804				MapViewToViewModel<TView>();
 805				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, instance);
 806				return this;
 807			}
 808
 809
 810			public ViewModelToViewMapper<TModel> MapToDefault<TView>(bool alwaysNew = true) where TView : class,IView
 811			{
 812				MapViewToViewModel<TView>();
 813				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(null, d => (TView)Activator.CreateInstance(typeof(TView), d as object), alwaysNew);
 814				return this;
 815			}
 816			public ViewModelToViewMapper<TModel> MapTo<TView>(string viewMappingKey, bool alwaysNew = true) where TView : class,IView
 817			{
 818				MapViewToViewModel<TView>();
 819				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, d => (TView)Activator.CreateInstance(typeof(TView), d as object), alwaysNew);
 820				return this;
 821			}
 822
 823			public ViewModelToViewMapper<TModel> MapToDefault<TView>(Func<TModel, TView> factory, bool alwaysNew = true) where TView : class,IView
 824			{
 825				MapViewToViewModel<TView>();
 826				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(null, d => factory((TModel)d), alwaysNew);
 827				return this;
 828			}
 829
 830			public ViewModelToViewMapper<TModel> MapTo<TView>(string viewMappingKey, Func<TModel, TView> factory, bool alwaysNew = true) where TView : class,IView
 831			{
 832				MapViewToViewModel<TView>();
 833				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, d => factory((TModel)d), alwaysNew);
 834				return this;
 835			}
 836#else
 837			public ViewModelToViewMapper<TModel> MapToDefaultControl<TControl>(TControl instance) where TControl : MVVMControl
 838			{
 839				MapViewToViewModel<TControl>();
 840				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(instance);
 841				return this;
 842			}
 843
 844			public ViewModelToViewMapper<TModel> MapToControl<TControl>(string viewMappingKey, TControl instance) where TControl : MVVMControl
 845			{
 846				MapViewToViewModel<TControl>();
 847				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, instance);
 848				return this;
 849			}
 850
 851
 852			public ViewModelToViewMapper<TModel> MapToDefaultControl<TControl>(bool alwaysNew = true) where TControl : MVVMControl
 853			{
 854				MapViewToViewModel<TControl>();
 855				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(null, d => (TControl)Activator.CreateInstance(typeof(TControl), d as object), alwaysNew);
 856				return this;
 857			}
 858			public ViewModelToViewMapper<TModel> MapToControl<TControl>(string viewMappingKey, bool alwaysNew = true) where TControl : MVVMControl
 859			{
 860				MapViewToViewModel<TControl>();
 861				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, d => (TControl)Activator.CreateInstance(typeof(TControl), d as object), alwaysNew);
 862				return this;
 863			}
 864
 865			public ViewModelToViewMapper<TModel> MapToDefaultControl<TControl>(Func<TModel, TControl> factory, bool alwaysNew = true) where TControl : MVVMControl
 866			{
 867				MapViewToViewModel<TControl>();
 868				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(null, d => factory((TModel)d), alwaysNew);
 869				return this;
 870			}
 871
 872			public ViewModelToViewMapper<TModel> MapToControl<TControl>(string viewMappingKey, Func<TModel, TControl> factory, bool alwaysNew = true) where TControl : MVVMControl
 873			{
 874				MapViewToViewModel<TControl>();
 875				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, d => factory((TModel)d), alwaysNew);
 876				return this;
 877			}
 878#endif
 879
 880#if WINDOWS_PHONE_8||WINDOWS_PHONE_7||SILVERLIGHT_5
 881            private static Uri GuessViewUri<TPage>(Uri baseUri) where TPage : MVVMPage
 882            {
 883                MapViewToViewModel<TPage>();
 884
 885                baseUri = baseUri ?? new Uri("/", UriKind.Relative);
 886
 887
 888                if (baseUri.IsAbsoluteUri)
 889                {
 890                    var path = Path.Combine(baseUri.LocalPath, typeof(TPage).Name + ".xaml");
 891                    UriBuilder ub = new UriBuilder(baseUri);
 892                    ub.Path = path;
 893                    return ub.Uri;
 894                }
 895                else
 896                {
 897                    var path = Path.Combine(baseUri.OriginalString, typeof(TPage).Name + ".xaml");
 898                    var pageUri = new Uri(path, UriKind.Relative);
 899                    return pageUri;
 900                }
 901            }
 902
 903            public ViewModelToViewMapper<TModel> MapToDefault<TPage>(Uri baseUri = null) where TPage : MVVMPage
 904            {
 905                MapViewToViewModel<TPage>();
 906                var pageUri = GuessViewUri<TPage>(baseUri);
 907                ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(
 908                    Tuple.Create<Uri, Func<IView>>(pageUri,
 909                    () => Activator.CreateInstance(typeof(TPage)) as IView
 910                    ));
 911                return this;
 912            }
 913
 914
 915
 916
 917            public ViewModelToViewMapper<TModel> MapTo<TPage>(string viewMappingKey, Uri baseUri = null) where TPage : MVVMPage
 918            {
 919                MapViewToViewModel<TPage>();
 920                var pageUri = GuessViewUri<TPage>(baseUri);
 921                ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(Tuple.Create<Uri, Func<IView>>(pageUri,
 922                        () => Activator.CreateInstance(typeof(TPage)) as IView
 923                        ));
 924                return this;
 925            }
 926
 927            //public ViewModelToViewMapper<TModel> MapToDefault(Uri pageUri)
 928            //{
 929            //    ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(pageUri);
 930            //    return this;
 931            //}
 932
 933            //public ViewModelToViewMapper<TModel> MapTo(string viewMappingKey, Uri pageUri)
 934            //{
 935            //    ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, pageUri);
 936            //    return this;
 937            //}
 938#endif
 939#if NETFX_CORE
 940
 941
 942
 943			public ViewModelToViewMapper<TModel> MapToDefault<TPage>() where TPage : MVVMPage
 944			{
 945
 946				MapViewToViewModel<TPage>();
 947				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(typeof(TPage));
 948				return this;
 949			}
 950
 951
 952			public ViewModelToViewMapper<TModel> MapToDefault<TPage>(string viewMappingKey) where TPage : MVVMPage
 953			{
 954				MapViewToViewModel<TPage>();
 955				ViewModelToViewMapperServiceLocator<TModel>.Instance.Register(viewMappingKey, typeof(TPage));
 956				return this;
 957			}
 958
 959
 960
 961#endif
 962
 963
 964		}
 965
 966		public static class ViewModelToViewMapperHelper
 967		{
 968
 969			internal static Dictionary<Type, Func<IViewModel>> ViewToVMMapping = new Dictionary<Type, Func<IViewModel>>();
 970
 971			public static IViewModel GetDefaultViewModel(this IView view)
 972			{
 973				Func<IViewModel> func;
 974				var vt = view.GetType();
 975				if (ViewModelToViewMapperHelper.ViewToVMMapping.TryGetValue(vt, out func))
 976				{
 977					return func();
 978				}
 979				return null;
 980			}
 981
 982			public static ViewModelToViewMapper<TViewModel> GetViewMapper<TViewModel>(this MVVMSidekick.Services.ServiceLocatorEntryStruct<TViewModel> vmRegisterEntry)
 983				  where TViewModel : IViewModel
 984			{
 985				return new ViewModelToViewMapper<TViewModel>();
 986			}
 987
 988		}
 989		public class ViewModelToViewMapperServiceLocator<TViewModel> : MVVMSidekick.Services.TypeSpecifiedServiceLocatorBase<ViewModelToViewMapperServiceLocator<TViewModel>, object>
 990		{
 991			static ViewModelToViewMapperServiceLocator()
 992			{
 993				Instance = new ViewModelToViewMapperServiceLocator<TViewModel>();
 994			}
 995			public static ViewModelToViewMapperServiceLocator<TViewModel> Instance { get; set; }
 996
 997
 998		}
 999		public class ViewModelLocator<TViewModel> : MVVMSidekick.Services.TypeSpecifiedServiceLocatorBase<ViewModelLocator<TViewModel>, TViewModel>
1000			where TViewModel : IViewModel
1001		{
1002			static ViewModelLocator()
1003			{
1004				Instance = new ViewModelLocator<TViewModel>();
1005			}
1006			public static ViewModelLocator<TViewModel> Instance { get; set; }
1007
1008		}
1009
1010
1011		public class Stage : DependencyObject
1012		{
1013			public Stage(FrameworkElement target, string beaconKey, StageManager navigator)
1014			{
1015				Target = target;
1016				_navigator = navigator;
1017				BeaconKey = beaconKey;
1018				//SetupNavigateFrame();
1019			}
1020
1021			StageManager _navigator;
1022			FrameworkElement _target;
1023
1024
1025
1026
1027			public Frame Frame
1028			{
1029				get { return (Frame)GetValue(FrameProperty); }
1030				private set { SetValue(FrameProperty, value); }
1031			}
1032
1033			// Using a DependencyProperty as the backing store for Frame.  This enables animation, styling, binding, etc...
1034			public static readonly DependencyProperty FrameProperty =
1035				DependencyProperty.Register("Frame", typeof(Frame), typeof(Stage), new PropertyMetadata(null));
1036
1037
1038
1039			public FrameworkElement Target
1040			{
1041				get { return _target; }
1042				private set
1043				{
1044					_target = value;
1045					Frame = _target as Frame;
1046
1047
1048				}
1049			}
1050#if WPF
1051			public bool IsGoForwardSupported
1052			{
1053				get
1054				{
1055					return Frame != null;
1056				}
1057			}
1058
1059			public bool CanGoForward
1060			{
1061				get
1062				{
1063					return IsGoForwardSupported ? Frame.CanGoForward : false;
1064				}
1065
1066			}
1067#else
1068			public bool IsGoForwardSupported
1069			{
1070				get
1071				{
1072					return false;
1073				}
1074			}
1075
1076			public bool CanGoForward
1077			{
1078				get
1079				{
1080					return false;
1081				}
1082
1083			}
1084#endif
1085			public bool IsGoBackSupported
1086			{
1087				get
1088				{
1089					return Frame != null;
1090				}
1091			}
1092
1093
1094			public bool CanGoBack
1095			{
1096				get
1097				{
1098					return IsGoBackSupported ? Frame.CanGoBack : false;
1099				}
1100
1101			}
1102
1103
1104
1105
1106			public string BeaconKey
1107			{
1108				get { return (string)GetValue(BeaconKeyProperty); }
1109				private set { SetValue(BeaconKeyProperty, value); }
1110			}
1111
1112			// Using a DependencyProperty as the backing store for BeaconKey.  This enables animation, styling, binding, etc...
1113			public static readonly DependencyProperty BeaconKeyProperty =
1114				DependencyProperty.Register("BeaconKey", typeof(string), typeof(Stage), new PropertyMetadata(""));
1115
1116
1117#if WPF
1118			private static IView InternalLocateViewIfNotSet<TTarget>(TTarget targetViewModel, string viewMappingKey, IView view) where TTarget : class, IViewModel
1119			{
1120				if (targetViewModel != null && targetViewModel.StageManager != null)
1121				{
1122					view = targetViewModel.StageManager.CurrentBindingView as IView;
1123
1124				}
1125				view = view ?? ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel) as IView;
1126				return view;
1127			}
1128
1129
1130
1131
1132
1133			public async Task Show<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1134				 where TTarget : class,IViewModel
1135			{
1136				IView view = null;
1137				view = InternalLocateViewIfNotSet<TTarget>(targetViewModel, viewMappingKey, view);
1138				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1139				if (view.ViewType == ViewType.Page)
1140				{
1141					var mvpg = view as MVVMPage;
1142					mvpg.Frame = Frame;
1143				}
1144
1145				SetVMAfterLoad(targetViewModel, view);
1146				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1147				await targetViewModel.WaitForClose();
1148			}
1149
1150
1151			public async Task<TResult> Show<TTarget, TResult>(TTarget targetViewModel = null, string viewMappingKey = null)
1152				where TTarget : class,IViewModel<TResult>
1153			{
1154				IView view = null;
1155				view = InternalLocateViewIfNotSet<TTarget>(targetViewModel, viewMappingKey, view);
1156				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1157
1158				if (view.ViewType == ViewType.Page)
1159				{
1160					var mvpg = view as MVVMPage;
1161					mvpg.Frame = Frame;
1162				}
1163
1164				SetVMAfterLoad(targetViewModel, view);
1165
1166				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1167				return await targetViewModel.WaitForCloseWithResult();
1168			}
1169
1170
1171
1172			public async Task<ShowAwaitableResult<TTarget>> ShowAndGetViewModel<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1173				where TTarget : class,IViewModel
1174			{
1175				IView view = null;
1176				view = InternalLocateViewIfNotSet<TTarget>(targetViewModel, viewMappingKey, view);
1177
1178				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1179				if (view.ViewType == ViewType.Page)
1180				{
1181					var mvpg = view as MVVMPage;
1182					mvpg.Frame = Frame;
1183				}
1184
1185				SetVMAfterLoad(targetViewModel, view);
1186				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1187
1188
1189				return await TaskExHelper.FromResult(new ShowAwaitableResult<TTarget> { Closing = targetViewModel.WaitForClose(), ViewModel = targetViewModel });
1190			}
1191#endif
1192#if SILVERLIGHT_5||WINDOWS_PHONE_7||WINDOWS_PHONE_8
1193
1194            internal Dictionary<string, IViewModel> NavigateRequestContexts
1195            {
1196                get
1197                {
1198
1199                    return GetNavigateRequestContexts(Frame);
1200                }
1201
1202                set
1203                {
1204                    SetNavigateRequestContexts(Frame, value);
1205                }
1206
1207            }
1208
1209            public static Dictionary<string, IViewModel> GetNavigateRequestContexts(DependencyObject obj)
1210            {
1211                return (Dictionary<string, IViewModel>)obj.GetValue(NavigateRequestContextsProperty);
1212            }
1213
1214            public static void SetNavigateRequestContexts(DependencyObject obj, Dictionary<string, IViewModel> value)
1215            {
1216                obj.SetValue(NavigateRequestContextsProperty, value);
1217            }
1218
1219            // Using a DependencyProperty as the backing store for NavigateRequestContexts.  This enables animation, styling, binding, etc...
1220            public static readonly DependencyProperty NavigateRequestContextsProperty =
1221                DependencyProperty.RegisterAttached("NavigateRequestContexts", typeof(Dictionary<string, IViewModel>), typeof(Stage), new PropertyMetadata(new Dictionary<string, IViewModel>()));
1222
1223            public async Task Show<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1224                 where TTarget : class,IViewModel
1225            {
1226
1227                var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1228
1229
1230
1231                Tuple<Uri, Func<IView>> uriData;
1232                uriData = item as Tuple<Uri, Func<IView>>;
1233                if (uriData != null) //only sl like page Can be registered as uri
1234                {
1235                    Frame frame;
1236                    if ((frame = Target as Frame) != null)
1237                    {
1238                        targetViewModel = await FrameNavigate<TTarget>(targetViewModel, uriData, frame);
1239                        await targetViewModel.WaitForClose();
1240                        return;
1241                    }
1242                    else
1243                    {
1244                        item = uriData.Item2();
1245                    }
1246                }
1247
1248                IView view = item as IView;
1249                targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1250                SetVMAfterLoad(targetViewModel, view);
1251                InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1252                await targetViewModel.WaitForClose();
1253            }
1254
1255
1256            public async Task<TResult> Show<TTarget, TResult>(TTarget targetViewModel = null, string viewMappingKey = null)
1257                where TTarget : class,IViewModel<TResult>
1258            {
1259
1260                var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1261
1262                Tuple<Uri, Func<IView>> uriData;
1263                if ((uriData = item as Tuple<Uri, Func<IView>>) != null) //only sl like page Can be registered as uri
1264                {
1265                    Frame frame;
1266                    if ((frame = Target as Frame) != null)
1267                    {
1268                        targetViewModel = await FrameNavigate<TTarget>(targetViewModel, uriData, frame);
1269
1270                        return await targetViewModel.WaitForCloseWithResult();
1271                    }
1272                    else
1273                    {
1274                        item = uriData.Item2();
1275                    }
1276                }
1277                IView view = item as IView;
1278                targetViewModel = targetViewModel ?? view.ViewModel as TTarget;		
1279                SetVMAfterLoad(targetViewModel, view);								
1280                InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1281                return await targetViewModel.WaitForCloseWithResult();
1282            }
1283
1284            private async Task<TTarget> FrameNavigate<TTarget>(TTarget targetViewModel, Tuple<Uri, Func<IView>> uriData, Frame frame) where TTarget : class,IViewModel
1285            {
1286                var t = new TaskCompletionSource<object>();
1287                var guid = Guid.NewGuid();
1288                var newUriWithParameter = new Uri(uriData.Item1.ToString() + "?CallBackGuid=" + guid.ToString(), UriKind.Relative);
1289
1290                var dis = EventRouting.EventRouter.Instance.GetEventObject<System.Windows.Navigation.NavigationEventArgs>()
1291
1292                    .Where(e =>
1293                            e.EventArgs.Uri == newUriWithParameter)
1294                    .Subscribe(e =>
1295                    {
1296                        var key = newUriWithParameter.ToString();
1297
1298                        lock (NavigateRequestContexts)
1299                        {
1300                            IViewModel vm = null;
1301
1302                            if (NavigateRequestContexts.TryGetValue(key, out vm))
1303                            {
1304                                targetViewModel = vm as TTarget;
1305                            }
1306
1307                            var page = e.Sender as MVVMPage;
1308
1309                            if (targetViewModel != null)
1310                            {
1311                                page.ViewModel = targetViewModel;
1312               
1313                            }
1314                            else
1315                            {
1316                                var solveV = page.GetDefaultViewModel();
1317                                if (solveV != null)
1318                                {
1319
1320                                    page.ViewModel = solveV;
1321                                }
1322
1323                            }
1324
1325                            targetViewModel = (TTarget)page.ViewModel;
1326                            NavigateRequestContexts[key] = targetViewModel;
1327                        }
1328                        if (!t.Task.IsCompleted)
1329                        {
1330
1331                            targetViewModel.AddDisposeAction(() =>
1332                            {
1333                                lock (NavigateRequestContexts)
1334                                {
1335                                    NavigateRequestContexts.Remove(key);
1336                                }
1337
1338                            });
1339                            t.SetResult(null);
1340                        }
1341                    }
1342                    );
1343
1344
1345
1346                frame.Navigate(newUriWithParameter);
1347                await t.Task;
1348                dis.DisposeWith(targetViewModel);
1349                return targetViewModel;
1350            }
1351
1352
1353
1354            public async Task<ShowAwaitableResult<TTarget>> ShowAndGetViewModel<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1355                where TTarget : class,IViewModel
1356            {
1357                var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1358                Tuple<Uri, Func<IView>> uriData;
1359                if ((uriData = item as Tuple<Uri, Func<IView>>) != null) //only sl like page Can be registered as uri
1360                {
1361                    Frame frame;
1362                    if ((frame = Target as Frame) != null)
1363                    {
1364                        targetViewModel = await FrameNavigate<TTarget>(targetViewModel, uriData, frame);
1365
1366                        return new ShowAwaitableResult<TTarget> { Closing = targetViewModel.WaitForClose(), ViewModel = targetViewModel };
1367
1368                    }
1369                    else
1370                    {
1371                        item = uriData.Item2();
1372
1373                    }
1374                }
1375
1376
1377                IView view = item as IView;
1378                targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1379                SetVMAfterLoad(targetViewModel, view);
1380                InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1381                var tr = targetViewModel.WaitForClose();
1382                return new ShowAwaitableResult<TTarget> { Closing = targetViewModel.WaitForClose(), ViewModel = targetViewModel };
1383            }
1384
1385#endif
1386
1387
1388			private static void SetVMAfterLoad<TTarget>(TTarget targetViewModel, IView view) where TTarget : class, IViewModel
1389			{
1390				if (view == null)
1391				{
1392					throw new InvalidOperationException(
1393						string.Format(@"
1394Cannot find ANY mapping from View Model [{0}] to ANY View.
1395Please check startup function of this mapping is well configured and be proper called while application starting",
1396						targetViewModel.GetType().ToString()));
1397				}
1398				if (view.ViewType == ViewType.Page)
1399				{
1400					var pg = view as MVVMPage;
1401
1402					pg.ViewModel = targetViewModel;
1403				}
1404				view.ViewModel = targetViewModel;
1405
1406				//var frview = view as FrameworkElement;
1407				//RoutedEventHandler loadEvent = null;
1408				//loadEvent = (_1, _2) =>
1409				//{
1410				//    view.ViewModel = targetViewModel;
1411				//    frview.Loaded -= loadEvent;
1412				//};
1413				//frview.Loaded += loadEvent;
1414
1415			}
1416
1417#if NETFX_CORE
1418
1419
1420
1421
1422			public async Task Show<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1423				 where TTarget : class,IViewModel
1424			{
1425
1426
1427				var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1428				Type type;
1429				if ((type = item as Type) != null) //only MVVMPage Can be registered as Type
1430				{
1431
1432					var frame = Target as Frame;
1433					if (frame != null)
1434					{
1435						targetViewModel = await FrameNavigate<TTarget>(targetViewModel, type, frame);
1436
1437						await targetViewModel.WaitForClose();
1438						return;
1439					}
1440
1441				}
1442
1443				IView view = item as IView;
1444				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1445				SetVMAfterLoad(targetViewModel, view);
1446				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1447				await targetViewModel.WaitForClose();
1448
1449
1450			}
1451
1452			private static async Task<TTarget> FrameNavigate<TTarget>(TTarget targetViewModel, Type type, Windows.UI.Xaml.Controls.Frame frame) where TTarget : class, IViewModel
1453			{
1454				var parameter = new StageNavigationContext<TTarget>() { ViewModel = targetViewModel };
1455				var t = new TaskCompletionSource<object>();
1456				var dip = EventRouting.EventRouter.Instance
1457					 .GetEventObject<NavigationEventArgs>()
1458
1459					 .Where(e =>
1460							 object.ReferenceEquals(e.EventArgs.Parameter, parameter))
1461					 .Subscribe(e =>
1462					 {
1463
1464						 var page = e.Sender as MVVMPage;
1465
1466						 if (parameter.ViewModel != null)
1467						 {
1468							 page.ViewModel = parameter.ViewModel;
1469						 }
1470						 else
1471						 {
1472							 var solveV = page.GetDefaultViewModel();
1473							 if (solveV != null)
1474							 {
1475								 targetViewModel = parameter.ViewModel = (TTarget)solveV;
1476							 }
1477						 }
1478
1479						 if (targetViewModel == null)
1480						 {
1481							 targetViewModel = (TTarget)page.ViewModel;
1482						 }
1483
1484
1485
1486
1487
1488						 parameter.ViewModel = targetViewModel;
1489
1490						 if (!t.Task.IsCompleted)
1491						 {
1492
1493							 t.SetResult(null); ;
1494						 }
1495					 });
1496
1497
1498				frame.Navigate(type, parameter);
1499				await t.Task;
1500				dip.DisposeWith(targetViewModel);
1501				return targetViewModel;
1502			}
1503			class StageNavigationContext<T> where T : IViewModel
1504			{
1505				public T ViewModel { get; set; }
1506
1507			}
1508			public async Task<TResult> Show<TTarget, TResult>(TTarget targetViewModel = null, string viewMappingKey = null)
1509				where TTarget : class,IViewModel<TResult>
1510			{
1511				var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1512				Type type;
1513				if ((type = item as Type) != null) //only MVVMPage Can be registered as Type
1514				{
1515					Frame frame;
1516					if ((frame = Target as Frame) != null)
1517					{
1518						targetViewModel = await FrameNavigate<TTarget>(targetViewModel, type, frame);
1519
1520
1521
1522
1523						return await targetViewModel.WaitForCloseWithResult();
1524					}
1525
1526				}
1527
1528
1529				IView view = item as IView;
1530				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1531				SetVMAfterLoad(targetViewModel, view);
1532				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1533				return await targetViewModel.WaitForCloseWithResult();
1534			}
1535
1536
1537
1538			public async Task<ShowAwaitableResult<TTarget>> ShowAndGetViewModel<TTarget>(TTarget targetViewModel = null, string viewMappingKey = null)
1539	where TTarget : class,IViewModel
1540			{
1541				var item = ViewModelToViewMapperServiceLocator<TTarget>.Instance.Resolve(viewMappingKey, targetViewModel);
1542				Type type;
1543				if ((type = item as Type) != null) //only MVVMPage Can be registered as Type
1544				{
1545					Frame frame;
1546					if ((frame = Target as Frame) != null)
1547					{
1548						targetViewModel = await FrameNavigate<TTarget>(targetViewModel, type, frame);
1549
1550						return new ShowAwaitableResult<TTarget>
1551						{
1552							Closing = targetViewModel.WaitForClose(),
1553							ViewModel = targetViewModel
1554						};
1555					}
1556
1557				}
1558
1559
1560				IView view = item as IView;
1561
1562				targetViewModel = targetViewModel ?? view.ViewModel as TTarget;
1563				SetVMAfterLoad(targetViewModel, view);
1564				InternalShowView(view, Target, _navigator.CurrentBindingView.ViewModel);
1565
1566				var tr = targetViewModel.WaitForClose();
1567				return new ShowAwaitableResult<TTarget> { Closing = tr, ViewModel = targetViewModel };
1568			}
1569#endif
1570
1571
1572
1573			private void InternalShowView(IView view, FrameworkElement target, IViewModel sourceVM)
1574			{
1575
1576				if (view is UserControl || view is Page)
1577				{
1578
1579					if (target is ContentControl)
1580					{
1581						var targetCControl = target as ContentControl;
1582						var oldcontent = targetCControl.Content as IDisposable;
1583
1584
1585						targetCControl.Content = view;
1586					}
1587					else if (target is Panel)
1588					{
1589						var targetPanelControl = target as Panel;
1590
1591						targetPanelControl.Children.Add(view as UIElement);
1592					}
1593					else
1594					{
1595						throw new InvalidOperationException(string.Format("This view {0} is not support show in {1} ", view.GetType(), target.GetType()));
1596					}
1597				}
1598#if WPF
1599				else if (view is Window)
1600				{
1601					var viewWindow = view as Window;
1602					viewWindow.HorizontalAlignment = HorizontalAlignment.Center;
1603					viewWindow.VerticalAlignment = VerticalAlignment.Center;
1604					var targetWindow = target as Window;
1605					if (targetWindow == null)
1606					{
1607						targetWindow = sourceVM.StageManager.CurrentBindingView as Window;
1608
1609					}
1610
1611					viewWindow.Owner = targetWindow;
1612					viewWindow.Show();
1613
1614				}
1615#endif
1616			}
1617
1618
1619		}
1620
1621		/// <summary>
1622		/// The abstract  for frame/contentcontrol. VM can access this class to Show other vm and vm's mapped view.
1623		/// </summary>
1624		public class StageManager : DependencyObject
1625		{
1626
1627
1628			static StageManager()
1629			{
1630				NavigatorBeaconsKey = "NavigatorBeaconsKey";
1631			}
1632			public StageManager(IViewModel viewModel)
1633			{
1634				_ViewModel = viewModel;
1635
1636
1637			}
1638			IViewModel _ViewModel;
1639
1640			/// <summary>
1641			/// This Key is a prefix for register keys. 
1642			/// The stage registeration store the String-Element-Mapping in view's Resource Dictionary(Resource property). 
1643			/// This can help not to overwrite the resources already defined.
1644			/// </summary>
1645			public static string NavigatorBeaconsKey;
1646
1647
1648
1649			IView _CurrentBindingView;
1650			/// <summary>
1651			/// Get the currently binded view of this stagemanager. A stagemanager is for a certain view. If viewmodel is not binded to a view, the whole thing cannot work.
1652			/// </summary>
1653			public IView CurrentBindingView
1654			{
1655				get
1656				{
1657
1658					return _CurrentBindingView;
1659				}
1660				internal set
1661				{
1662					_CurrentBindingView = value;
1663				}
1664			}
1665
1666
1667
1668
1669
1670
1671
1672			public void InitParent(Func<DependencyObject> parentLocator)
1673			{
1674				_parentLocator = parentLocator;
1675				DefaultStage = this[""];
1676			}
1677
1678
1679
1680			Func<DependencyObject> _parentLocator;
1681
1682
1683			#region Attached Property
1684
1685
1686#if WPF
1687			[AttachedPropertyBrowsableForType(typeof(ContentControl))]
1688			[AttachedPropertyBrowsableForType(typeof(Frame))]
1689			[AttachedPropertyBrowsableForType(typeof(Window))]
1690#endif
1691			public static string GetBeacon(DependencyObject obj)
1692			{
1693				return (string)obj.GetValue(BeaconProperty);
1694			}
1695
1696#if WPF
1697			[AttachedPropertyBrowsableForType(typeof(ContentControl))]
1698			[AttachedPropertyBrowsableForType(typeof(Frame))]
1699			[AttachedPropertyBrowsableForType(typeof(Window))]
1700#endif
1701
1702			public static void SetBeacon(DependencyObject obj, string value)
1703			{
1704				obj.SetValue(BeaconProperty, value);
1705			}
1706
1707			public static readonly DependencyProperty BeaconProperty =
1708				DependencyProperty.RegisterAttached("Beacon", typeof(string), typeof(StageManager), new PropertyMetadata(null,
1709					   (o, p) =>
1710					   {
1711						   var name = (p.NewValue as string);
1712						   var target = o as FrameworkElement;
1713
1714						   target.Loaded +=
1715							   (_1, _2)
1716							   =>
1717							   {
1718								   StageManager.RegisterTargetBeacon(name, target);
1719							   };
1720					   }
1721
1722					   ));
1723
1724
1725
1726
1727
1728			#endregion
1729
1730
1731			internal FrameworkElement LocateTargetContainer(IView view, ref string targetContainerName, IViewModel sourceVM)
1732			{
1733				targetContainerName = targetContainerName ?? "";
1734				var viewele = view as FrameworkElement;
1735				FrameworkElement target = null;
1736
1737
1738
1739				var dic = GetOrCreateBeacons(sourceVM.StageManager.CurrentBindingView as FrameworkElement);
1740				dic.TryGetValue(targetContainerName, out target);
1741
1742
1743				if (target == null)
1744				{
1745					target = _parentLocator() as FrameworkElement;
1746				}
1747
1748				if (target == null)
1749				{
1750					var vieweleCt = viewele as ContentControl;
1751					if (vieweleCt != null)
1752					{
1753						target = vieweleCt.Content as FrameworkElement;
1754					}
1755				}
1756				return target;
1757			}
1758
1759
1760
1761
1762			private static Dictionary<string, FrameworkElement> GetOrCreateBeacons(FrameworkElement view)
1763			{
1764				Dictionary<string, FrameworkElement> dic;
1765#if NETFX_CORE
1766				if (!view.Resources.ContainsKey(NavigatorBeaconsKey))
1767#else
1768				if (!view.Resources.Contains(NavigatorBeaconsKey))
1769#endif
1770				{
1771					dic = new Dictionary<string, FrameworkElement>();
1772					view.Resources.Add(NavigatorBeaconsKey, dic);
1773				}
1774				else
1775					dic = view.Resources[NavigatorBeaconsKey] as Dictionary<string, FrameworkElement>;
1776
1777				return dic;
1778			}
1779
1780			public static void RegisterTargetBeacon(string name, FrameworkElement target)
1781			{
1782				var view = LocateIView(target);
1783				var beacons = GetOrCreateBeacons(view);
1784
1785
1786				beacons[name] = target;
1787
1788
1789			}
1790
1791			private static FrameworkElement LocateIView(FrameworkElement target)
1792			{
1793
1794				var view = target;
1795
1796				while (view != null)
1797				{
1798					if (view is IView)
1799					{
1800						break;
1801					}
1802					view = view.Parent as FrameworkElement;
1803
1804				}
1805				return view;
1806			}
1807
1808
1809
1810
1811
1812
1813
1814			public Stage DefaultStage
1815			{
1816				get { return (Stage)GetValue(DefaultTargetProperty); }
1817				set { SetValue(DefaultTargetProperty, value); }
1818			}
1819
1820			// Using a DependencyProperty as the backing store for DefaultTarget.  This enables animation, styling, binding, etc...
1821			public static readonly DependencyProperty DefaultTargetProperty =
1822				DependencyProperty.Register("DefaultTarget", typeof(Stage), typeof(StageManager), new PropertyMetadata(null));
1823
1824
1825
1826			public Stage this[string beaconKey]
1827			{
1828				get
1829				{
1830					var fr = LocateTargetContainer(CurrentBindingView, ref beaconKey, _ViewModel);
1831					if (fr != null)
1832					{
1833						return new Stage(fr, beaconKey, this);
1834					}
1835					else
1836						return null;
1837				}
1838			}
1839		}
1840
1841
1842
1843
1844		public class PropertyBridge : FrameworkElement
1845		{
1846			public PropertyBridge()
1847			{
1848				base.Width = 0;
1849				base.Height = 0;
1850				base.Visibility = Visibility.Collapsed;
1851
1852			}
1853
1854
1855
1856
1857			public object Source
1858			{
1859				private get { return (object)GetValue(SourceProperty); }
1860				set { SetValue(SourceProperty, value); }
1861			}
1862
1863			// Using a DependencyProperty as the backing store for Source.  This enables animation, styling, binding, etc...
1864			public static readonly DependencyProperty SourceProperty =
1865				DependencyProperty.Register("Source", typeof(object), typeof(PropertyBridge), new PropertyMetadata(null,
1866
1867					(o, a) =>
1868					{
1869						var pb = o as PropertyBridge;
1870						if (pb != null)
1871						{
1872							pb.Target = a.NewValue;
1873						}
1874					}
1875					));
1876
1877
1878
1879
1880			public object Target
1881			{
1882				get { return (object)GetValue(TargetProperty); }
1883				set { SetValue(TargetProperty, value); }
1884			}
1885
1886			// Using a DependencyProperty as the backing store for Target.  This enables animation, styling, binding, etc...
1887			public static readonly DependencyProperty 

Large files files are truncated, but you can click here to view the full file