Exemplo n.º 1
0
        /// <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 );
			};
		}