/// <summary> /// Initializes a new instance of the <see cref="ConventionsHanlder"/> class. /// </summary> /// <param name="broker">The broker.</param> /// <param name="releaser">The releaser.</param> /// <param name="bootstrapConventions">The Bootstrap Conventions</param> public ConventionsHanlder(IMessageBroker broker, IReleaseComponents releaser, BootstrapConventions bootstrapConventions) { this.broker = broker; this.releaser = releaser; this.bootstrapConventions = bootstrapConventions; this.DefaultResolveViewModelType = viewType => { var aName = new AssemblyName(viewType.Assembly.FullName); var vmTypeName = String.Format("{0}.{1}Model, {2}", viewType.Namespace, viewType.Name, aName.FullName); var vmType = Type.GetType(vmTypeName, false); return(vmType); }; this.ResolveViewModelType = viewType => { return(this.DefaultResolveViewModelType(viewType)); }; this.DefaultResolveViewType = viewModelType => { var aName = new AssemblyName(viewModelType.Assembly.FullName); var vTypeName = String.Format("{0}.{1}, {2}", viewModelType.Namespace, viewModelType.Name.Remove(viewModelType.Name.LastIndexOf('M')), aName.FullName); var vType = Type.GetType(vTypeName, true); return(vType); }; this.ResolveViewType = viewModelType => { return(this.DefaultResolveViewType(viewModelType)); }; this.DefaultViewReleaseHandler = (view, behavior) => { var autoDispose = view.GetType().IsAttributeDefined <ViewManualReleaseAttribute>() == false; if (autoDispose || behavior == ViewReleaseBehavior.Force) { var vm = this.GetViewDataContext(view, ViewDataContextSearchBehavior.LocalOnly); if (vm != null) { this.SetViewDataContext(view, null); if (this.ShouldUnsubscribeViewModelOnRelease(view)) { this.broker.Unsubscribe(vm); } this.releaser.Release(vm); } this.DetachViewBehaviors(view); this.releaser.Release(view); } }; this.ViewReleaseHandler = (view, behavior) => { this.DefaultViewReleaseHandler(view, behavior); }; Func <DependencyObject, Boolean> isSingletonView = view => { var implementation = view.GetType(); var contracts = this.bootstrapConventions.SelectViewContracts(implementation); var isShell = this.bootstrapConventions.IsShellView(contracts, implementation); return(isShell); }; this.DefaultShouldUnsubscribeViewModelOnRelease = view => !isSingletonView(view); this.ShouldUnsubscribeViewModelOnRelease = view => this.DefaultShouldUnsubscribeViewModelOnRelease(view); this.DefaultShouldReleaseView = view => !isSingletonView(view); this.ShouldReleaseView = view => this.DefaultShouldReleaseView(view); this.DefaultShouldUnregisterRegionManagerOfView = view => !isSingletonView(view); this.ShouldUnregisterRegionManagerOfView = view => this.DefaultShouldUnregisterRegionManagerOfView(view); this.DefaultFindHostingWindowOf = vm => { var view = this.GetViewOfViewModel(vm); var window = this.FindWindowOf(view); //.FindWindow(); return(window); }; this.FindHostingWindowOf = vm => { return(this.DefaultFindHostingWindowOf(vm)); }; this.DefaultFindWindowOf = dependencyObject => { var window = Window.GetWindow(dependencyObject); //.FindWindow(); return(window); }; this.FindWindowOf = dependencyObject => { return(this.DefaultFindWindowOf(dependencyObject)); }; this.DefaultViewHasDataContext = (view, behavior) => { return(this.GetViewDataContext(view, behavior) != null); }; this.ViewHasDataContext = (view, behavior) => { return(this.DefaultViewHasDataContext(view, behavior)); }; this.DefaultGetViewDataContext = (view, behavior) => { if (behavior == ViewDataContextSearchBehavior.Legacy) { if (view is FrameworkElement) { return((( FrameworkElement )view).DataContext); } #if !SILVERLIGHT else if (view is FrameworkContentElement) { return((( FrameworkContentElement )view).DataContext); } #endif } else { if (view is FrameworkElement) { var dc = view.ReadLocalValue(FrameworkElement.DataContextProperty); if (dc != DependencyProperty.UnsetValue) { return(dc); } } #if !SILVERLIGHT else if (view is FrameworkContentElement) { var dc = view.ReadLocalValue(FrameworkContentElement.DataContextProperty); if (dc != DependencyProperty.UnsetValue) { return(dc); } } #endif } return(null); }; this.GetViewDataContext = (view, behavior) => { return(this.DefaultGetViewDataContext(view, behavior)); }; this.DefaultSetViewDataContext = (view, dc) => { if (view is FrameworkElement) { (( FrameworkElement )view).DataContext = dc; } #if !SILVERLIGHT else if (view is FrameworkContentElement) { (( FrameworkContentElement )view).DataContext = dc; } #endif }; this.SetViewDataContext = (view, dc) => { this.DefaultSetViewDataContext(view, dc); }; this.DefaultTryHookClosedEventOfHostOf = (view, closedCallback) => { //dobbiamo anche cercare una IClosableView oltre che una Window var window = this.FindWindowOf(view); if (window != null) { #if SILVERLIGHT EventHandler <System.ComponentModel.ClosingEventArgs> closing = null; closing = (s, e) => { try { closedCallback(window); } finally { window.Closing -= closing; } }; window.Closing += closing; #else EventHandler closed = null; closed = (s, e) => { try { closedCallback(window); } finally { window.Closed -= closed; } }; window.Closed += closed; #endif } return(window); }; this.TryHookClosedEventOfHostOf = (view, closedCallback) => { return(this.DefaultTryHookClosedEventOfHostOf(view, closedCallback)); }; this.DefaultIsHostingView = fe => fe.GetType().Name.EndsWith("View"); this.IsHostingView = fe => this.DefaultIsHostingView(fe); this.DefaultAttachViewToViewModel = (view, viewModel) => { viewModel.As <IViewModel>(i => { i.View = view; }); }; this.AttachViewToViewModel = (view, viewModel) => { this.DefaultAttachViewToViewModel(view, viewModel); }; this.DefaultGetViewOfViewModel = viewModel => { if (viewModel is IViewModel) { return((( IViewModel )viewModel).View); } return(null); }; this.GetViewOfViewModel = viewModel => { return(this.DefaultGetViewOfViewModel(viewModel)); }; #if !SILVERLIGHT this.DefaultAttachViewBehaviors = view => { var bhv = Interaction.GetBehaviors(view); if (view is Window && bhv.OfType <WindowLifecycleNotificationsBehavior>().None()) { bhv.Add(new WindowLifecycleNotificationsBehavior(this.broker, this)); } else if (view is FrameworkElement && bhv.OfType <FrameworkElementLifecycleNotificationsBehavior>().None()) { bhv.Add(new FrameworkElementLifecycleNotificationsBehavior(this.broker, this)); } if (bhv.OfType <DependencyObjectCloseHandlerBehavior>().None()) { bhv.Add(new DependencyObjectCloseHandlerBehavior(this.broker, this)); } }; this.AttachViewBehaviors = view => { this.DefaultAttachViewBehaviors(view); }; #else this.AttachViewBehaviors = view => { var bhv = Interaction.GetBehaviors(view); //if( view is Page ) //{ // bhv.Add( new PageNavigationNotifcationsBehavior( this.broker ) ); //} bhv.Add(new FrameworkElementLifecycleNotificationsBehavior(this.broker, this)); bhv.Add(new DependencyObjectCloseHandlerBehavior(this.broker, this)); }; #endif #if !SILVERLIGHT this.DefaultDetachViewBehaviors = view => { var bhv = Interaction.GetBehaviors(view); if (view is Window) { bhv.OfType <WindowLifecycleNotificationsBehavior>().ToList().ForEach(x => bhv.Remove(x)); } else if (view is FrameworkElement) { bhv.OfType <FrameworkElementLifecycleNotificationsBehavior>().ToList().ForEach(x => bhv.Remove(x)); } bhv.OfType <DependencyObjectCloseHandlerBehavior>().ToList().ForEach(x => bhv.Remove(x)); }; this.DetachViewBehaviors = view => { this.DefaultDetachViewBehaviors(view); }; #else this.DetachViewBehaviors = view => { var bhv = Interaction.GetBehaviors(view); bhv.OfType <FrameworkElementLifecycleNotificationsBehavior>().ToList().ForEach(x => bhv.Remove(x)); bhv.OfType <DependencyObjectCloseHandlerBehavior>().ToList().ForEach(x => bhv.Remove(x)); }; #endif this.DefaultShouldNotifyViewModelLoaded = (view, dataContext) => { if (dataContext == null) { return(false); } var hasAttribute = dataContext.GetType().IsAttributeDefined <NotifyLoadedAttribute>(); var hasRegions = RegionService.CurrentService.HoldsRegionManager(view); return(hasAttribute || hasRegions); }; this.ShouldNotifyViewModelLoaded = (view, dataContext) => { return(this.DefaultShouldNotifyViewModelLoaded(view, dataContext)); }; this.DefaultShouldNotifyViewLoaded = view => { /* * we should decide if the attribute must be applied on the view or, as in this fix, * mainly for backward compatibility, can be applied also on the ViewModel and the * _View_Loaded message is still broadcasted. */ //var dataContext = this.GetViewDataContext( view ); //var hasAttributeOnViewModel = dataContext != null && dataContext.GetType().IsAttributeDefined<NotifyLoadedAttribute>(); var hasAttributeOnView = view.GetType().IsAttributeDefined <NotifyLoadedAttribute>(); var hasRegions = RegionService.CurrentService.HoldsRegionManager(view); return /* hasAttributeOnViewModel || */ (hasAttributeOnView || hasRegions); }; this.ShouldNotifyViewLoaded = view => { return(this.DefaultShouldNotifyViewLoaded(view)); }; }
/// <summary> /// Initializes a new instance of the <see cref="ConventionsHanlder"/> class. /// </summary> /// <param name="broker">The broker.</param> /// <param name="releaser">The releaser.</param> /// <param name="bootstrapConventions">The Bootstrap Conventions</param> public ConventionsHanlder( IMessageBroker broker, IReleaseComponents releaser, BootstrapConventions bootstrapConventions ) { this.broker = broker; this.releaser = releaser; this.bootstrapConventions = bootstrapConventions; this.DefaultResolveViewModelType = viewType => { var aName = new AssemblyName( viewType.Assembly.FullName ); var vmTypeName = String.Format( "{0}.{1}Model, {2}", viewType.Namespace, viewType.Name, aName.FullName ); var vmType = Type.GetType( vmTypeName, false ); return vmType; }; this.ResolveViewModelType = viewType => { return this.DefaultResolveViewModelType( viewType ); }; this.DefaultResolveViewType = viewModelType => { var aName = new AssemblyName( viewModelType.Assembly.FullName ); var vTypeName = String.Format( "{0}.{1}, {2}", viewModelType.Namespace, viewModelType.Name.Remove( viewModelType.Name.LastIndexOf( 'M' ) ), aName.FullName ); var vType = Type.GetType( vTypeName, true ); return vType; }; this.ResolveViewType = viewModelType => { return this.DefaultResolveViewType( viewModelType ); }; this.DefaultViewReleaseHandler = ( view, behavior ) => { var autoDispose = view.GetType().IsAttributeDefined<ViewManualReleaseAttribute>() == false; if( autoDispose || behavior == ViewReleaseBehavior.Force ) { var vm = this.GetViewDataContext( view, ViewDataContextSearchBehavior.LocalOnly ); if( vm != null ) { this.SetViewDataContext( view, null ); if( this.ShouldUnsubscribeViewModelOnRelease( view ) ) { this.broker.Unsubscribe( vm ); } this.releaser.Release( vm ); } this.DetachViewBehaviors( view ); this.releaser.Release( view ); } }; this.ViewReleaseHandler = ( view, behavior ) => { this.DefaultViewReleaseHandler( view, behavior ); }; Func<DependencyObject, Boolean> isSingletonView = view => { var implementation = view.GetType(); var contracts = this.bootstrapConventions.SelectViewContracts( implementation ); var isShell = this.bootstrapConventions.IsShellView( contracts, implementation ); return isShell; }; this.DefaultShouldUnsubscribeViewModelOnRelease = view => !isSingletonView( view ); this.ShouldUnsubscribeViewModelOnRelease = view => this.DefaultShouldUnsubscribeViewModelOnRelease( view ); this.DefaultShouldReleaseView = view => !isSingletonView( view ); this.ShouldReleaseView = view => this.DefaultShouldReleaseView( view ); this.DefaultShouldUnregisterRegionManagerOfView = view => !isSingletonView( view ); this.ShouldUnregisterRegionManagerOfView = view => this.DefaultShouldUnregisterRegionManagerOfView( view ); this.DefaultFindHostingWindowOf = vm => { var view = this.GetViewOfViewModel( vm ); var window = this.FindWindowOf( view );//.FindWindow(); return window; }; this.FindHostingWindowOf = vm => { return this.DefaultFindHostingWindowOf( vm ); }; this.DefaultFindWindowOf = dependencyObject => { var window = Window.GetWindow( dependencyObject );//.FindWindow(); return window; }; this.FindWindowOf = dependencyObject => { return this.DefaultFindWindowOf(dependencyObject); }; this.DefaultViewHasDataContext = ( view, behavior ) => { return this.GetViewDataContext( view, behavior ) != null; }; this.ViewHasDataContext = ( view, behavior ) => { return this.DefaultViewHasDataContext( view, behavior ); }; this.DefaultGetViewDataContext = ( view, behavior ) => { if( behavior == ViewDataContextSearchBehavior.Legacy ) { if( view is FrameworkElement ) { return ( ( FrameworkElement )view ).DataContext; } #if !SILVERLIGHT else if( view is FrameworkContentElement ) { return ( ( FrameworkContentElement )view ).DataContext; } #endif } else { if( view is FrameworkElement ) { var dc = view.ReadLocalValue( FrameworkElement.DataContextProperty ); if( dc != DependencyProperty.UnsetValue ) { return dc; } } #if !SILVERLIGHT else if( view is FrameworkContentElement ) { var dc = view.ReadLocalValue( FrameworkContentElement.DataContextProperty ); if( dc != DependencyProperty.UnsetValue ) { return dc; } } #endif } return null; }; this.GetViewDataContext = ( view, behavior ) => { return this.DefaultGetViewDataContext( view, behavior ); }; this.DefaultSetViewDataContext = ( view, dc ) => { if( view is FrameworkElement ) { ( ( FrameworkElement )view ).DataContext = dc; } #if !SILVERLIGHT else if( view is FrameworkContentElement ) { ( ( FrameworkContentElement )view ).DataContext = dc; } #endif }; this.SetViewDataContext = ( view, dc ) => { this.DefaultSetViewDataContext( view, dc ); }; this.DefaultTryHookClosedEventOfHostOf = ( view, closedCallback ) => { //dobbiamo anche cercare una IClosableView oltre che una Window var window = this.FindWindowOf( view ); if( window != null ) { #if SILVERLIGHT EventHandler<System.ComponentModel.ClosingEventArgs> closing = null; closing = ( s, e ) => { try { closedCallback( window ); } finally { window.Closing -= closing; } }; window.Closing += closing; #else EventHandler closed = null; closed = ( s, e ) => { try { closedCallback( window ); } finally { window.Closed -= closed; } }; window.Closed += closed; #endif } return window; }; this.TryHookClosedEventOfHostOf = ( view, closedCallback ) => { return this.DefaultTryHookClosedEventOfHostOf( view, closedCallback ); }; this.DefaultIsHostingView = fe => fe.GetType().Name.EndsWith( "View" ); this.IsHostingView = fe => this.DefaultIsHostingView( fe ); this.DefaultAttachViewToViewModel = ( view, viewModel ) => { viewModel.As<IViewModel>( i => { i.View = view; } ); }; this.AttachViewToViewModel = ( view, viewModel ) => { this.DefaultAttachViewToViewModel( view, viewModel ); }; this.DefaultGetViewOfViewModel = viewModel => { if( viewModel is IViewModel ) { return ( ( IViewModel )viewModel ).View; } return null; }; this.GetViewOfViewModel = viewModel => { return this.DefaultGetViewOfViewModel( viewModel ); }; #if !SILVERLIGHT this.DefaultAttachViewBehaviors = view => { var bhv = Interaction.GetBehaviors( view ); if( view is Window && bhv.OfType<WindowLifecycleNotificationsBehavior>().None() ) { bhv.Add( new WindowLifecycleNotificationsBehavior( this.broker, this ) ); } else if( view is FrameworkElement && bhv.OfType<FrameworkElementLifecycleNotificationsBehavior>().None() ) { bhv.Add( new FrameworkElementLifecycleNotificationsBehavior( this.broker, this ) ); } if( bhv.OfType<DependencyObjectCloseHandlerBehavior>().None() ) { bhv.Add( new DependencyObjectCloseHandlerBehavior( this.broker, this ) ); } }; this.AttachViewBehaviors = view => { this.DefaultAttachViewBehaviors( view ); }; #else this.AttachViewBehaviors = view => { var bhv = Interaction.GetBehaviors( view ); //if( view is Page ) //{ // bhv.Add( new PageNavigationNotifcationsBehavior( this.broker ) ); //} bhv.Add( new FrameworkElementLifecycleNotificationsBehavior( this.broker, this ) ); bhv.Add( new DependencyObjectCloseHandlerBehavior( this.broker, this ) ); }; #endif #if !SILVERLIGHT this.DefaultDetachViewBehaviors = view => { var bhv = Interaction.GetBehaviors( view ); if( view is Window ) { bhv.OfType<WindowLifecycleNotificationsBehavior>().ToList().ForEach( x => bhv.Remove( x ) ); } else if( view is FrameworkElement ) { bhv.OfType<FrameworkElementLifecycleNotificationsBehavior>().ToList().ForEach( x => bhv.Remove( x ) ); } bhv.OfType<DependencyObjectCloseHandlerBehavior>().ToList().ForEach( x => bhv.Remove( x ) ); }; this.DetachViewBehaviors = view => { this.DefaultDetachViewBehaviors( view ); }; #else this.DetachViewBehaviors = view => { var bhv = Interaction.GetBehaviors( view ); bhv.OfType<FrameworkElementLifecycleNotificationsBehavior>().ToList().ForEach( x => bhv.Remove( x ) ); bhv.OfType<DependencyObjectCloseHandlerBehavior>().ToList().ForEach( x => bhv.Remove( x ) ); }; #endif this.DefaultShouldNotifyViewModelLoaded = ( view, dataContext ) => { if( dataContext == null ) { return false; } var hasAttribute = dataContext.GetType().IsAttributeDefined<NotifyLoadedAttribute>(); var hasRegions = RegionService.CurrentService.HoldsRegionManager( view ); return hasAttribute || hasRegions; }; this.ShouldNotifyViewModelLoaded = ( view, dataContext ) => { return this.DefaultShouldNotifyViewModelLoaded( view, dataContext ); }; this.DefaultShouldNotifyViewLoaded = view => { /* * we should decide if the attribute must be applied on the view or, as in this fix, * mainly for backward compatibility, can be applied also on the ViewModel and the * _View_Loaded message is still broadcasted. */ //var dataContext = this.GetViewDataContext( view ); //var hasAttributeOnViewModel = dataContext != null && dataContext.GetType().IsAttributeDefined<NotifyLoadedAttribute>(); var hasAttributeOnView = view.GetType().IsAttributeDefined<NotifyLoadedAttribute>(); var hasRegions = RegionService.CurrentService.HoldsRegionManager( view ); return /* hasAttributeOnViewModel || */ hasAttributeOnView || hasRegions; }; this.ShouldNotifyViewLoaded = view => { return this.DefaultShouldNotifyViewLoaded( view ); }; }