public override void Dispose()
 {
     lock (_syncObj)
     {
         Detach();
         if (_bindingDependency != null)
         {
             _bindingDependency.Detach();
             _bindingDependency = null;
         }
         // Child bindings will be disposed automatically by DependencyObject.Dispose, because they are
         // added to our binding collection (was done by method AddChild)
         ResetBindingAttachments();
         base.Dispose();
     }
 }
        public void Dispose(bool passSourceToContextObject)
        {
            Detach();
            if (_bindingDependency != null)
            {
                _bindingDependency.Detach();
                _bindingDependency = null;
            }
            ResetChangeHandlerAttachments();
            MPF.TryCleanupAndDispose(_valueConverter);
            object source = Source;

            if (passSourceToContextObject && source != null)
            {
                _contextObject.TakeOverOwnership(source);
            }
            else
            {
                MPF.TryCleanupAndDispose(source);
            }
            base.Dispose();
        }
        protected bool UpdateBinding()
        {
            // Avoid recursive calls: For instance, this can occur when the later call to Evaluate will change our evaluated
            // source value, which will cause a recursive call to UpdateBinding.
            if (_isUpdatingBinding)
            {
                return(false);
            }
            _isUpdatingBinding = true;
            try
            {
                if (KeepBinding) // This is the case if our target descriptor has a binding type
                {                // In this case, this instance should be used rather than the evaluated source value
                    if (_targetDataDescriptor != null)
                    {
                        _contextObject.SetBindingValue(_targetDataDescriptor, this);
                    }
                    _valueAssigned = true;
                    return(true);
                }
                IDataDescriptor sourceDd;
                lock (_syncObj)
                    if (!Evaluate(out sourceDd))
                    {
                        _valueAssigned = false;
                        return(false);
                    }

                // We're called multiple times, for example when a resource dictionary changes.
                // To avoid too many updates, we remember the last updated value.
                if (ReferenceEquals(sourceDd, _lastUpdatedValue) && !_valueAssigned)
                {
                    return(true);
                }
                _lastUpdatedValue = sourceDd;

                // Don't lock the following lines because the binding dependency object updates source or target objects.
                // Holding a lock during that process would offend against the MP2 threading policy.

                if (_bindingDependency != null)
                {
                    _bindingDependency.Detach();
                }
                _bindingDependency = null;
                switch (Mode)
                {
                case BindingMode.TwoWay:
                case BindingMode.OneWayToSource:
                    throw new XamlBindingException(
                              "MultiBindingMarkupExtension doesn't support BindingMode.TwoWay and BindingMode.OneWayToSource");

                case BindingMode.OneTime:
                    object value = sourceDd.Value;
                    _contextObject.SetBindingValue(_targetDataDescriptor, value);
                    _valueAssigned = true;
                    Dispose();
                    return(true); // In this case, we have finished with only assigning the value

                default:          // Mode == BindingMode.OneWay || Mode == BindingMode.Default
                    _bindingDependency = new BindingDependency(sourceDd, _targetDataDescriptor, true,
                                                               UpdateSourceTrigger.Explicit, null, null, null);
                    _valueAssigned = true;
                    break;
                }
                return(true);
            }
            finally
            {
                _isUpdatingBinding = false;
            }
        }
    protected virtual bool UpdateBinding()
    {
      // Avoid recursive calls: For instance, this can occur when
      // the later call to Evaluate will change our evaluated source value, which
      // will cause a recursive call to UpdateBinding.
      if (_isUpdatingBinding)
        return false;
      _isUpdatingBinding = true;
      try
      {
        if (KeepBinding) // This is the case if our target descriptor has a binding type
        { // In this case, this instance should be used rather than the evaluated source value
          if (_targetDataDescriptor != null)
            _contextObject.SetBindingValue(_targetDataDescriptor, this);
          _valueAssigned = true;
          return true;
        }
        IDataDescriptor sourceDd;
        if (!Evaluate(out sourceDd))
        {
          _valueAssigned = false;
          return false;
        }

        // We're called multiple times, for example when a resource dictionary changes.
        // To avoid too many updates, we remember the last updated value.
        if (ReferenceEquals(sourceDd, _lastUpdatedValue) && !_valueAssigned)
          return true;
        _lastUpdatedValue = sourceDd;

#if DEBUG_BINDINGS
        DebugOutput("UpdateBinding: Binding evaluated to '{0}'", sourceDd.Value);
#endif

        if (_bindingDependency != null)
          _bindingDependency.Detach();

        bool attachToSource = false;
        bool attachToTarget = false;
        switch (Mode)
        {
          case BindingMode.Default:
          case BindingMode.OneWay:
            // Currently, we don't really support the Default binding mode in
            // MediaPortal skin engine. Maybe we will support it in future -
            // then we'll be able to initialize the mode with a default value
            // implied by our target data endpoint.
            attachToSource = true;
            break;
          case BindingMode.TwoWay:
            attachToSource = true;
            attachToTarget = true;
            break;
          case BindingMode.OneWayToSource:
            attachToTarget = true;
            break;
          case BindingMode.OneTime:
            object value = sourceDd.Value;
            object convertedValue;
            if (!Convert(value, _targetDataDescriptor.DataType, out convertedValue))
              return false;
            _contextObject.SetBindingValue(_targetDataDescriptor,
                ReferenceEquals(value, convertedValue) ? MpfCopyManager.DeepCopyCutLVPs(convertedValue) : convertedValue);
            _valueAssigned = true;
            Dispose(true);
            return true; // In this case, we have finished with only assigning the value
        }
        DependencyObject parent;
        if (UpdateSourceTrigger != UpdateSourceTrigger.LostFocus ||
            !FindAncestor(_contextObject, out parent, FindParentMode.HybridPreferVisualTree, -1, typeof(UIElement)))
          parent = null;
        _bindingDependency = new BindingDependency(sourceDd, _targetDataDescriptor, attachToSource,
            attachToTarget ? UpdateSourceTrigger : UpdateSourceTrigger.Explicit,
            parent as UIElement, _valueConverter, _converterParameter);
        _valueAssigned = true;
        return true;
      }
      finally
      {
        _isUpdatingBinding = false;
      }
    }
 public void Dispose(bool passSourceToContextObject)
 {
   Detach();
   if (_bindingDependency != null)
   {
     _bindingDependency.Detach();
     _bindingDependency = null;
   }
   ResetChangeHandlerAttachments();
   MPF.TryCleanupAndDispose(_valueConverter);
   object source = Source;
   if (passSourceToContextObject && source != null)
     _contextObject.TakeOverOwnership(source);
   else
     MPF.TryCleanupAndDispose(source);
   base.Dispose();
 }
        protected virtual bool UpdateBinding()
        {
            // Avoid recursive calls: For instance, this can occur when
            // the later call to Evaluate will change our evaluated source value, which
            // will cause a recursive call to UpdateBinding.
            if (_isUpdatingBinding)
            {
                return(false);
            }
            _isUpdatingBinding = true;
            try
            {
                if (KeepBinding) // This is the case if our target descriptor has a binding type
                {                // In this case, this instance should be used rather than the evaluated source value
                    if (_targetDataDescriptor != null)
                    {
                        _contextObject.SetBindingValue(_targetDataDescriptor, this);
                    }
                    _valueAssigned = true;
                    return(true);
                }
                IDataDescriptor sourceDd;
                if (!Evaluate(out sourceDd))
                {
                    _valueAssigned = false;
                    return(false);
                }

                // We're called multiple times, for example when a resource dictionary changes.
                // To avoid too many updates, we remember the last updated value.
                if (ReferenceEquals(sourceDd, _lastUpdatedValue) && !_valueAssigned)
                {
                    return(true);
                }
                _lastUpdatedValue = sourceDd;

#if DEBUG_BINDINGS
                DebugOutput("UpdateBinding: Binding evaluated to '{0}'", sourceDd.Value);
#endif

                if (_bindingDependency != null)
                {
                    _bindingDependency.Detach();
                }

                bool attachToSource = false;
                bool attachToTarget = false;
                switch (Mode)
                {
                case BindingMode.Default:
                case BindingMode.OneWay:
                    // Currently, we don't really support the Default binding mode in
                    // MediaPortal skin engine. Maybe we will support it in future -
                    // then we'll be able to initialize the mode with a default value
                    // implied by our target data endpoint.
                    attachToSource = true;
                    break;

                case BindingMode.TwoWay:
                    attachToSource = true;
                    attachToTarget = true;
                    break;

                case BindingMode.OneWayToSource:
                    attachToTarget = true;
                    break;

                case BindingMode.OneTime:
                    object value = sourceDd.Value;
                    object convertedValue;
                    if (!Convert(value, _targetDataDescriptor.DataType, out convertedValue))
                    {
                        return(false);
                    }
                    _contextObject.SetBindingValue(_targetDataDescriptor,
                                                   ReferenceEquals(value, convertedValue) ? MpfCopyManager.DeepCopyCutLVPs(convertedValue) : convertedValue);
                    _valueAssigned = true;
                    Dispose(true);
                    return(true); // In this case, we have finished with only assigning the value
                }
                DependencyObject parent;
                if (UpdateSourceTrigger != UpdateSourceTrigger.LostFocus ||
                    !FindAncestor(_contextObject, out parent, FindParentMode.HybridPreferVisualTree, -1, typeof(UIElement)))
                {
                    parent = null;
                }
                _bindingDependency = new BindingDependency(sourceDd, _targetDataDescriptor, attachToSource,
                                                           attachToTarget ? UpdateSourceTrigger : UpdateSourceTrigger.Explicit,
                                                           parent as UIElement, _valueConverter, _converterParameter);
                _valueAssigned = true;
                return(true);
            }
            finally
            {
                _isUpdatingBinding = false;
            }
        }