private bool CanBind( IWindowElement target, IWindowElement origin, BindingPosition position, out SpatialBinding targetSpatialBinding, out SpatialBinding originSpatialBinding )
        {
            Debug.Assert( Dispatcher.CurrentDispatcher == Application.Current.Dispatcher, "This method should only be called by the Application Thread." );

            originSpatialBinding = null;
            using( _logger.OpenGroup( LogLevel.Info, "Master binding..." ) )
            {
                if( _spatialBindings.TryGetValue( target, out targetSpatialBinding ) )
                {
                    if( position == BindingPosition.Top && targetSpatialBinding.Top != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Top.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Left && targetSpatialBinding.Left != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Left.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Bottom && targetSpatialBinding.Bottom != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Bottom.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Right && targetSpatialBinding.Right != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", targetSpatialBinding.Right.Window.Name, target.Name, position );
                        return false;
                    }
                    else _logger.Trace( "{0} already exists in bindings but no window attached at position {1}.", target.Name, position );
                }
                else
                {
                    _logger.Trace( "Fresh new window" );
                }
            }

            using( _logger.OpenGroup( LogLevel.Info, "Slave binding..." ) )
            {
                if( _spatialBindings.TryGetValue( origin, out originSpatialBinding ) )
                {
                    if( position == BindingPosition.Top && originSpatialBinding.Bottom != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Bottom.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Left && originSpatialBinding.Right != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Right.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Bottom && originSpatialBinding.Top != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Top.Window.Name, target.Name, position );
                        return false;
                    }
                    else if( position == BindingPosition.Right && originSpatialBinding.Left != null )
                    {
                        _logger.Trace( "{0} is already bound to {1} at position {2}.", originSpatialBinding.Left.Window.Name, target.Name, position );
                        return false;
                    }
                    else _logger.Trace( "{0} already exists in bindings but no window attached at position {1}.", origin.Name, position );
                }
                else
                {
                    _logger.Trace( "Fresh new window" );
                    //spatialBinding = new SpatialBinding( slave );
                }
            }

            return true;
        }
        public void Bind( IWindowElement master, IWindowElement slave, BindingPosition position, bool saveBinding = false )
        {
            if( Dispatcher.CurrentDispatcher != Application.Current.Dispatcher ) throw new InvalidOperationException( "This method should only be called by the Application Thread." );

            if( master == null ) throw new ArgumentNullException( "master" );
            if( slave == null ) throw new ArgumentNullException( "slave" );

            //Console.WriteLine( "BIND thread id: {0} TimeSpan : {1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now.Ticks );

            // Spatial binding point of view
            using( _logger.OpenGroup( LogLevel.Info, "Attaching {0} on {1} at {2}", master.Name, slave.Name, position.ToString() ) )
            {
                SpatialBinding spatialBinding = null;
                SpatialBinding slaveSpatialBinding = null;

                if( CanBind( master, slave, position, out spatialBinding, out slaveSpatialBinding ) )
                {
                    _logger.Trace( "Before binding..." );

                    var binding = new SimpleBinding
                    {
                        Target = master,
                        Origin = slave,
                        Position = position
                    };

                    var evt = new WindowBindingEventArgs
                    {
                        Binding = binding,
                        BindingType = BindingEventType.Attach
                    };

                    if( BeforeBinding != null )
                        BeforeBinding( this, evt );

                    if( evt.Canceled == true )
                    {
                        _logger.Trace( "...canceled. The reason was {0}.", evt.CancelReason ?? "No Reason" );
                    }
                    else
                    {
                        if( spatialBinding == null )
                        {
                            spatialBinding = new SpatialBinding( master );
                            _spatialBindings.Add( master, spatialBinding );
                        }
                        if( slaveSpatialBinding == null )
                        {
                            slaveSpatialBinding = new SpatialBinding( slave );
                            _spatialBindings.Add( slave, slaveSpatialBinding );
                        }

                        Debug.Assert( spatialBinding != null );
                        Debug.Assert( slaveSpatialBinding != null );

                        //TODO : FIXWITHDOCKING

                        if( position == BindingPosition.Top )
                        {
                            spatialBinding.Top = slaveSpatialBinding;
                            slaveSpatialBinding.Bottom = spatialBinding;
                        }
                        if( position == BindingPosition.Left )
                        {
                            spatialBinding.Left = slaveSpatialBinding;
                            slaveSpatialBinding.Right = spatialBinding;
                        }
                        if( position == BindingPosition.Bottom )
                        {
                            spatialBinding.Bottom = slaveSpatialBinding;
                            slaveSpatialBinding.Top = spatialBinding;
                        }
                        if( position == BindingPosition.Right )
                        {
                            spatialBinding.Right = slaveSpatialBinding;
                            slaveSpatialBinding.Left = spatialBinding;
                        }

                        if( saveBinding )
                            _persistantBindings.Add( binding );

                        var evtAfter = new WindowBindedEventArgs
                        {
                            Binding = binding,
                            BindingType = BindingEventType.Attach
                        };

                        _logger.Trace( "After binding..." );
                        if( AfterBinding != null )
                            AfterBinding( this, evtAfter );
                    }
                }
            }
        }