BindingExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Data / BindingExpression.cs / 1305600 / BindingExpression.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Defines BindingExpression object, the run-time instance of data binding. 
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.ComponentModel;
using System.Globalization; 
using System.Windows.Threading;
using System.Threading;
using System.Xml;
using System.Windows; 
using System.Windows.Input;
using System.Windows.Controls; 
using System.Windows.Markup; 
using MS.Utility;
using MS.Internal; 
using MS.Internal.Controls; // Validation
using MS.Internal.Data;
using MS.Internal.KnownBoxes;
using MS.Internal.Utility;  // TraceLog 

namespace System.Windows.Data 
{ 

 
    /// 
    /// called whenever any exception is encountered when trying to update
    /// the value to the source. The application author can provide its own
    /// handler for handling exceptions here. If the delegate returns 
    ///     null - dont throw an error or provide a ValidationError.
    ///     Exception - returns the exception itself, we will fire the exception using Async exception model. 
    ///     ValidationError - it will set itself as the BindingInError and add it to the elements Validation errors. 
    /// 
    public delegate object UpdateSourceExceptionFilterCallback(object bindExpression, Exception exception); 

    /// 
    ///  Describes a single run-time instance of data binding, binding a target
    ///  (element, DependencyProperty) to a source (object, property, XML node) 
    /// 
    public sealed class BindingExpression : BindingExpressionBase, IDataBindEngineClient, IWeakEventListener 
    { 
        //-----------------------------------------------------
        // 
        //  Enums
        //
        //-----------------------------------------------------
 
        internal enum SourceType { Unknown, CLR, XML }
        private enum AttachAttempt { First, Again, Last } 
 
        //------------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        private BindingExpression(Binding binding, BindingExpressionBase owner)
            : base(binding, owner) 
        { 
            UseDefaultValueConverter = (ParentBinding.Converter == null);
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ShowPath))
            {
                PropertyPath pp = binding.Path;
                string path = (pp != null) ? pp.Path : String.Empty; 

                if (String.IsNullOrEmpty(binding.XPath)) 
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BindingPath( 
                                            TraceData.Identify(path)));
                }
                else
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BindingXPathAndPath( 
                                            TraceData.Identify(binding.XPath), 
                                            TraceData.Identify(path)));
                } 
            }
        }

        //------------------------------------------------------ 
        //
        //  Interfaces 
        // 
        //------------------------------------------------------
 
        void IDataBindEngineClient.TransferValue()
        {
            TransferValue();
        } 

        void IDataBindEngineClient.UpdateValue() 
        { 
            UpdateValue();
        } 

        bool IDataBindEngineClient.AttachToContext(bool lastChance)
        {
            AttachToContext(lastChance ? AttachAttempt.Last : AttachAttempt.Again); 
            return (Status != BindingStatus.Unattached);
        } 
 
        void IDataBindEngineClient.VerifySourceReference(bool lastChance)
        { 
            DependencyObject target = TargetElement;
            ObjectRef sourceRef = ParentBinding.SourceReference;
            DependencyObject mentor = !UsingMentor ? target : Helper.FindMentor(target);
            ObjectRefArgs args = new ObjectRefArgs() { 
                                    ResolveNamesInTemplate = ResolveNamesInTemplate,
                                    }; 
            object source = sourceRef.GetDataObject(mentor, args); 

            if (source != DataItem) 
            {
                // the source reference resolves differently from before, so
                // re-attach to the tree context
                AttachToContext(lastChance ? AttachAttempt.Last : AttachAttempt.Again); 
            }
        } 
 
        void IDataBindEngineClient.OnTargetUpdated()
        { 
            OnTargetUpdated();
        }

        DependencyObject IDataBindEngineClient.TargetElement 
        {
            get { return TargetElement; } 
        } 

        //----------------------------------------------------- 
        //
        //  Public Properties
        //
        //------------------------------------------------------ 

        ///  Binding from which this expression was created  
        public Binding ParentBinding { get { return (Binding)ParentBindingBase; } } 

        /// The data item actually used by this BindingExpression 
        public object DataItem { get { return GetReference(_dataItem); } }

        /// The data source actually used by this BindingExpression
        internal object DataSource 
        {
            get 
            { 
                DependencyObject target = TargetElement;
                if (target == null) 
                    return null;

                // if we're using DataContext, find the source for the DataContext
                if (_ctxElement != null) 
                    return GetDataSourceForDataContext(ContextElement);
 
                // otherwise use the explicit source 
                ObjectRef or = ParentBinding.SourceReference;
                return or.GetObject(target, new ObjectRefArgs()); 
            }
        }

        //----------------------------------------------------- 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
 
        ///  Send the current value back to the source 
        ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource 
        public override void UpdateSource()
        { 
            if (Status == BindingStatus.Detached)
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionIsDetached)); 
 
            NeedsUpdate = true;     // force update
            Update(true);           // update synchronously 
        }

        ///  Force a data transfer from source to target 
        public override void UpdateTarget() 
        {
            if (Status == BindingStatus.Detached) 
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionIsDetached)); 

            if (Worker != null) 
            {
                Worker.RefreshValue();  // calls TransferValue
            }
        } 

#region Expression overrides 
 
        /// 
        ///     Called to evaluate the Expression value 
        /// 
        /// DependencyObject being queried
        /// Property being queried
        /// Computed value. Default (of the target) if unavailable. 
        internal override object GetValue(DependencyObject d, DependencyProperty dp)
        { 
            return Value; 
        }
 
        /// 
        ///     Allows Expression to store set values
        /// 
        /// DependencyObject being set 
        /// Property being set
        /// Value being set 
        /// true if Expression handled storing of the value 
        internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value)
        { 
            if (IsReflective)
            {
                Value = value;
                return true; 
            }
            else 
            { 
                // if the binding doesn't push values back to the source, allow
                // SetValue to overwrite the binding with a local value 
                return false;
            }
        }
 
        /// 
        ///     Notification that a Dependent that this Expression established has 
        ///     been invalidated as a result of a Source invalidation 
        /// 
        /// DependencyObject that was invalidated 
        /// Changed event args for the property that was invalidated
        internal override void OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            if (d == null) 
                throw new ArgumentNullException("d");
            if (args == null) 
                throw new ArgumentNullException("args"); 

            DependencyProperty dp = args.Property; 
            if (dp == null)
                throw new InvalidOperationException(SR.Get(SRID.ArgumentPropertyMustNotBeNull, "Property", "args"));

            // ignore irrelevant notifications.  This test must happen before any marshalling. 
            bool relevant = !IgnoreSourcePropertyChange;
 
            if (dp == FrameworkElement.DataContextProperty && d == ContextElement) 
            {
                relevant = true;    // changes from context element are always relevant 
            }
            else if (dp == CollectionViewSource.ViewProperty && d == CollectionViewSource)
            {
                relevant = true;    // changes from the CollectionViewSource are always relevant 
            }
            else if (dp == FrameworkElement.LanguageProperty && UsesLanguage && d == TargetElement) 
            { 
                relevant = true;    // changes from target's Language are always relevant
            } 
            else if (relevant)
            {
                relevant = (Worker != null) && (Worker.UsesDependencyProperty(d, dp));
            } 

            if (!relevant) 
                return; 

            base.OnPropertyInvalidation(d, args); 
        }

#endregion  Expression overrides
 
        //-----------------------------------------------------
        // 
        //  Protected Methods 
        //
        //------------------------------------------------------ 

        /// 
        /// Invalidate the given child expression.
        ///  
        internal override void InvalidateChild(BindingExpressionBase bindingExpression)
        { 
            // BindingExpression does not support child bindings 
        }
 
        /// 
        /// Change the dependency sources for the given child expression.
        /// 
        internal override void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources) 
        {
            // BindingExpression does not support child bindings 
        } 

        ///  
        /// Replace the given child expression with a new one.
        /// 
        internal override void ReplaceChild(BindingExpressionBase bindingExpression)
        { 
            // BindingExpression does not support child bindings
        } 
 
        // register the leaf bindings with the binding group
        internal override void UpdateBindingGroup(BindingGroup bg) 
        {
            bg.UpdateTable(this);
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Properties 
        //
        //------------------------------------------------------ 

        // The ContextElement is the DependencyObject (if any) whose DataContext
        // is used as the starting point for the evaluation of the BindingExpression Path.
        //      We should not store a strong reference to the context element, 
        // for the same reasons as mentioned above for TargetElement.  Instead,
        // we store a weak reference.  Callers should be prepared for the case 
        // ContextElement==null, which is different from _ctxElement==null.  The 
        // former means the BindingExpression uses a context element, but that element has
        // been GC'd;  the latter means that the BindingExpression does not use a context 
        // element.
        internal DependencyObject ContextElement
        {
            get 
            {
                if (_ctxElement != null) 
                    return _ctxElement.Target as DependencyObject; 
                else
                    return null; 
            }
        }

        // The CollectionViewSource is the source object, as a CollectionViewSource. 
        internal CollectionViewSource CollectionViewSource
        { 
            get { return (CollectionViewSource)GetReference(_collectionViewSource); } 
            set { _collectionViewSource = CreateReference(value); }
        } 

        ///  True if this binding expression should ignore changes from the source 
        internal bool IgnoreSourcePropertyChange
        { 
            get
            { 
                if (IsTransferPending || IsInUpdate) 
                    return true;
 
                return false;
            }
        }
 
        internal PropertyPath Path
        { 
            get { return ParentBinding.Path; } 
        }
 
        internal IValueConverter Converter
        {
            get { return _valueConverter; }
            set { _valueConverter = value; } 
        }
 
        // MultiBinding looks at this to find out what type its MultiValueConverter should 
        // convert back to, when this BindingExpression is not using a user-specified converter.
        internal Type ConverterSourceType 
        {
            get { return _sourceType; }
        }
 
        // the item whose property changes when we UpdateSource
        internal object SourceItem 
        { 
            get { return (Worker != null) ? Worker.SourceItem : null; }
        } 

        // the name of the property that changes when we UpdateSource
        internal string SourcePropertyName
        { 
            get { return (Worker != null) ? Worker.SourcePropertyName : null; }
        } 
 
        // the value of the source property
        internal object SourceValue 
        {
            get { return (Worker != null) ? Worker.RawValue() : DependencyProperty.UnsetValue; }
        }
 
        internal override bool IsParentBindingUpdateTriggerDefault
        { 
            get { return (ParentBinding.UpdateSourceTrigger == UpdateSourceTrigger.Default); } 
        }
 
        internal override bool IsDisconnected
        {
            get { return GetReference(_dataItem) == DisconnectedItem; }
        } 

        //------------------------------------------------------ 
        // 
        //  Internal Methods
        // 
        //-----------------------------------------------------

        // Create a new BindingExpression from the given Bind description
        internal static BindingExpression CreateBindingExpression(DependencyObject d, 
                                                DependencyProperty dp,
                                                Binding binding, 
                                                BindingExpressionBase parent) 
        {
            FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata; 

            if ((fwMetaData != null && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly)
                throw new ArgumentException(SR.Get(SRID.PropertyNotBindable, dp.Name), "dp");
 
            // create the BindingExpression
            BindingExpression bindExpr = new BindingExpression(binding, parent); 
 
            bindExpr.ResolvePropertyDefaultSettings(binding.Mode, binding.UpdateSourceTrigger, fwMetaData);
 
            // Two-way Binding with an empty path makes no sense
            if (bindExpr.IsReflective && binding.XPath == null &&
                    (binding.Path == null || String.IsNullOrEmpty(binding.Path.Path)))
                throw new InvalidOperationException(SR.Get(SRID.TwoWayBindingNeedsPath)); 

            return bindExpr; 
        } 

 
        // Note: For Nullable types, DefaultValueConverter is created for the inner type of the Nullable.
        //       Nullable "Drill-down" service is not provided for user provided Converters.
        internal void SetupDefaultValueConverter(Type type)
        { 
            if (!UseDefaultValueConverter)
                return; 
 
            if (IsInMultiBindingExpression)
            { 
                Converter = null;
                _sourceType = type;
            }
            else if (type != null && type != _sourceType) 
            {
                _sourceType = type; 
 
                Converter = Engine.GetDefaultValueConverter(_sourceType,
                                    TargetProperty.PropertyType, IsReflective); 

                // null converter means failure to create one
                if (Converter == null && TraceData.IsEnabled)
                { 
                     TraceData.Trace(TraceEventType.Error,
                                    TraceData.CannotCreateDefaultValueConverter( 
                                        _sourceType, 
                                        TargetProperty.PropertyType,
                                        (IsReflective ? "two-way" : "one-way")), 
                                    this );
                }

                if (Converter == DefaultValueConverter.ValueConverterNotNeeded) 
                {
                    Converter = null;     // everyone else takes null for an answer. 
                } 
            }
        } 

        // return true if DataContext is set locally (not inherited) on DependencyObject
        internal static bool HasLocalDataContext(DependencyObject d)
        { 
            bool hasModifiers;
            BaseValueSourceInternal valueSource = d.GetValueSource(FrameworkElement.DataContextProperty, null, out hasModifiers); 
            return (valueSource != BaseValueSourceInternal.Inherited) && 
                    (valueSource != BaseValueSourceInternal.Default || hasModifiers);
        } 

        //------------------------------------------------------
        //
        //  Private Properties 
        //
        //----------------------------------------------------- 
 
        private bool CanActivate
        { 
            get { return Status != BindingStatus.Unattached; }
        }

        private BindingWorker Worker { get { return _worker; } } 

        private DynamicValueConverter DynamicConverter 
        { 
            get
            { 
                if (_dynamicConverter == null)
                {
                    Invariant.Assert(Worker != null);
                    // pass along the static source and target types to find same DefaultValueConverter as SetupDefaultValueConverter 
                    _dynamicConverter = new DynamicValueConverter(IsReflective, Worker.SourcePropertyType, Worker.TargetPropertyType);
                } 
                return _dynamicConverter; 
            }
        } 


        //-----------------------------------------------------
        // 
        //  Private Methods
        // 
        //----------------------------------------------------- 

#region Attachment 

        /// 
        /// Attach the binding expression to the given target object and property.
        ///  
        internal override bool AttachOverride(DependencyObject target, DependencyProperty dp)
        { 
            if (!base.AttachOverride(target, dp)) 
                return false;
 
            // listen for InheritanceContext change (if target is mentored)
            if (ParentBinding.SourceReference == null || ParentBinding.SourceReference.UsesMentor)
            {
                DependencyObject mentor = Helper.FindMentor(target); 
                if (mentor != target)
                { 
                    InheritanceContextChangedEventManager.AddListener(target, this); 
                    UsingMentor = true;
 
                    if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach))
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UseMentor( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(mentor))); 
                    } 
                }
            } 

            // listen for lost focus
            if (IsUpdateOnLostFocus)
            { 
                Invariant.Assert(!IsInMultiBindingExpression, "Source BindingExpressions of a MultiBindingExpression should never be UpdateOnLostFocus.");
                LostFocusEventManager.AddListener(target, this); 
            } 

            // attach to things that need tree context.  Do it synchronously 
            // if possible, otherwise post a task.  This gives the parser et al.
            // a chance to assemble the tree before we start walking it.
            AttachToContext(AttachAttempt.First);
            if (Status == BindingStatus.Unattached) 
            {
                if (TraceLog != null) 
                { 
                    string path = (ParentBinding.Path != null) ? ParentBinding.Path.Path : null;
                    TraceLog.Add("Defer attach to {0} of {1}, path = {2}  xpath = {3}", 
                        dp.Name, TraceLog.IdFor(target), path, ParentBinding.XPath);
                }
                Engine.AddTask(this, TaskOps.AttachToContext);
 
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.AttachToContext))
                { 
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.DeferAttachToContext(
                                            TraceData.Identify(this))); 
                }
            }

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831) 
            return true;
        } 
 

        ///  
        /// Detach the binding expression from its target object and property.
        /// 
        internal override void DetachOverride()
        { 
            if (TraceLog != null)
            { 
                TraceLog.Add("Detaching.  status = {0} {1}", Status, new StackTrace()); 
            }
 
            Deactivate();

            DetachFromContext();
 
            // detach from target element
            DependencyObject target = TargetElement; 
            if (target != null && IsUpdateOnLostFocus) 
            {
                LostFocusEventManager.RemoveListener(target, this); 
            }

            ChangeValue(DependencyProperty.UnsetValue, false);
 
            base.DetachOverride();
        } 
 
        // try to get information from the tree context (parent, root, etc.)
        // If everything succeeds, activate the binding. 
        // If anything fails in a way that might succeed after further layout,
        // just return (with status == Unattached).  The binding engine will try
        // again later. For hard failures, set an error status;  no more chances.
        // During the "last chance" attempt, treat all failures as "hard". 
        void AttachToContext(AttachAttempt attempt)
        { 
            // if the target has been GC'd, just give up 
            DependencyObject target = TargetElement;
            if (target == null) 
                return;     // status will be Detached

            if (TraceLog != null)
            { 
                TraceLog.Add("AttachToContext target = {0}, attempt = {1}", TraceLog.IdFor(target), attempt);
            } 
 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.AttachToContext);
            bool traceObjectRef = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.SourceLookup); 

            // certain features should never be tried on the first attempt, as
            // they certainly require at least one layout pass
            if (attempt == AttachAttempt.First) 
            {
                // relative source with ancestor lookup 
                ObjectRef or = ParentBinding.SourceReference; 
                if (or != null && or.TreeContextIsRequired(target))
                { 
                    if (isExtendedTraceEnabled)
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.SourceRequiresTreeContext( 
                                                TraceData.Identify(this),
                                                or.Identify())); 
                    } 

                    return; 
                }
            }

            bool lastChance = (attempt == AttachAttempt.Last); 

            if (isExtendedTraceEnabled) 
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.AttachToContext( 
                                        TraceData.Identify(this),
                                        lastChance ? " (last chance)" : String.Empty));
            }
 
            // if the path has unresolved type names, the parser needs namesapce
            // information to resolve them.  See XmlTypeMapper.GetTypeFromName. 
            // Ignore this requirement during the last chance, and just let 
            // GetTypeFromName fail if it wants to.
            if (!lastChance && ParentBinding.TreeContextIsRequired) 
            {
                if (target.GetValue(XmlAttributeProperties.XmlnsDictionaryProperty) == null ||
                    target.GetValue(XmlAttributeProperties.XmlNamespaceMapsProperty) == null)
                { 
                    if (isExtendedTraceEnabled)
                    { 
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.PathRequiresTreeContext(
                                                TraceData.Identify(this), 
                                                ParentBinding.Path.Path));
                    }

                    return; 
                }
            } 
 
            // if the binding uses a mentor, check that it exists
            DependencyObject mentor = !UsingMentor ? target :  Helper.FindMentor(target); 
            if (mentor == null)
            {
                if (isExtendedTraceEnabled)
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.NoMentorExtended( 
                                            TraceData.Identify(this))); 
                }
 
                if (lastChance)
                {
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoMentor, this); 
                    } 
                }
                return; 
            }

            // determine the element whose DataContext governs this BindingExpression
            DependencyObject contextElement = null;     // no context element 
            bool contextElementFound = true;
            if (ParentBinding.SourceReference == null) 
            { 
                contextElement = mentor;    // usually the mentor/target element
 
                // special cases:
                // 1. if target property is DataContext, use the target's parent.
                //      This enables  and
                // 2. if the target is ContentPresenter and the target property 
                //      is Content, use the parent.  This enables
                //           
                // 3. if target is CVS, and its inheritance context was set 
                //      via DataContext, use the mentor's parent.  This enables
                //        
                CollectionViewSource cvs;
                if (TargetProperty == FrameworkElement.DataContextProperty ||
                    (TargetProperty == ContentPresenter.ContentProperty &&
                            target is ContentPresenter) || 
                    (UsingMentor &&
                            (cvs = target as CollectionViewSource) != null && 
                            cvs.PropertyForInheritanceContext == FrameworkElement.DataContextProperty) 
                    )
                { 
                    contextElement = FrameworkElement.GetFrameworkParent(contextElement);
                    contextElementFound = (contextElement != null);
                }
            } 
            else
            { 
                RelativeObjectRef ror = ParentBinding.SourceReference as RelativeObjectRef; 
                if (ror != null && ror.ReturnsDataContext)
                { 
                    object o = ror.GetObject(mentor, new ObjectRefArgs() { IsTracing = traceObjectRef});
                    contextElement = o as DependencyObject;    // ref to another element's DataContext
                    contextElementFound = (o != DependencyProperty.UnsetValue);
                } 
            }
 
            if (isExtendedTraceEnabled) 
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.ContextElement(
                                        TraceData.Identify(this),
                                        TraceData.Identify(contextElement),
                                        contextElementFound ? "OK" : "error")); 
            }
 
            // if we need a context element, check that we found it 
            if (!contextElementFound)
            { 
                if (lastChance)
                {
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoDataContext, this); 
                    } 
                }
 
                return;
            }

            // determine the source object, from which the path evaluation starts 
            object source;
            ObjectRef sourceRef; 
 
            if (contextElement != null)
            { 
                source = contextElement.GetValue(FrameworkElement.DataContextProperty);

                // if the data context is default null, try again later;  future
                // layout may change the inherited value. 
                // Ignore this requirement during the last chance, and just let
                // the binding to null DataContext proceed. 
                if (source == null && !lastChance && !HasLocalDataContext(contextElement)) 
                {
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.NullDataContext(
                                                TraceData.Identify(this))); 
                    }
 
                    return; 
                }
            } 
            else if ((sourceRef = ParentBinding.SourceReference) != null)
            {
                ObjectRefArgs args = new ObjectRefArgs() {
                                        IsTracing = traceObjectRef, 
                                        ResolveNamesInTemplate = ResolveNamesInTemplate,
                                        }; 
                source = sourceRef.GetDataObject(mentor, args); 

                // check that the source could be found 
                if (source == DependencyProperty.UnsetValue)
                {
                    if (lastChance)
                    { 
                        SetStatus(BindingStatus.PathError);
                        if (TraceData.IsEnabled) 
                        { 
                            TraceData.Trace(TraceLevel, TraceData.NoSource(sourceRef), this);
                        } 
                    }

                    return;
                } 
                else if (!lastChance && args.NameResolvedInOuterScope)
                { 
                    // if ElementName resolved in an outer scope, it's possible 
                    // that future work might add the name to an inner scope.
                    // Schedule a task to check this. 
                    Engine.AddTask(this, TaskOps.VerifySourceReference);
                }
            }
            else 
            {
                // we get here only if we need ambient data context, but there 
                // is no context element.  E.g. binding the DataContext property 
                // of an element with no parent.  Just use null.
                source = null; 
            }

            // if we get this far, all the ingredients for a successful binding
            // are present.  Remember what we've found and activate the binding. 
            if (contextElement != null)
                _ctxElement = new WeakReference(contextElement); 
 
            // attach to context element
            ChangeWorkerSources(null, 0); 

            if (!UseDefaultValueConverter)
            {
                _valueConverter = ParentBinding.Converter; 

                if (_valueConverter == null) 
                { 
                    throw new InvalidOperationException(SR.Get(SRID.MissingValueConverter)); // report instead of throw?
                } 
            }

            // join the right binding group (if any)
            JoinBindingGroup(IsReflective, contextElement); 

            SetStatus(BindingStatus.Inactive); 
 
            // inner BindingExpressions of PriorityBindingExpressions may not need to be activated
            if (IsInPriorityBindingExpression) 
                ParentPriorityBindingExpression.InvalidateChild(this);
            else    // singular BindingExpressions and those in MultiBindingExpressions should always activate
                Activate(source);
 
            GC.KeepAlive(target);   // keep target alive during activation (bug 956831)
        } 
 
        // Detach from things that may require tree context
        private void DetachFromContext() 
        {
            // detach from data source
            if (_dataProvider != null)
            { 
                if (TraceLog != null)
                { 
                    TraceLog.Add("-OnDataChanged to {0}", TraceLog.IdFor(_dataProvider)); 
                }
                DataChangedEventManager.RemoveListener(_dataProvider, this); 
            }

            if (!UseDefaultValueConverter)
            { 
                _valueConverter = null;
            } 
 
            if (!IsInBindingExpressionCollection)
                ChangeSources(null); 

            if (UsingMentor)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                    InheritanceContextChangedEventManager.RemoveListener(target, this); 
            } 

            _ctxElement = null; 
        }

#endregion Attachment
 
#region Activation
 
        // Activate the BindingExpression, if necessary and possible 
        internal override void Activate()
        { 
            if (!CanActivate)
                return;

            if (_ctxElement == null) 
            {
                // only activate once if there's an explicit source 
                if (Status == BindingStatus.Inactive) 
                {
                    DependencyObject target = TargetElement; 
                    if (target != null)
                    {
                        if (UsingMentor)
                        { 
                            target = Helper.FindMentor(target);
                            if (target == null) 
                            { 
                                // mentor is not available
                                SetStatus(BindingStatus.PathError); 
                                if (TraceData.IsEnabled)
                                {
                                    TraceData.Trace(TraceEventType.Error, TraceData.NoMentor, this);
                                } 
                                return;
                            } 
                        } 
                        Activate(ParentBinding.SourceReference.GetDataObject(target,
                                                                new ObjectRefArgs() { ResolveNamesInTemplate = ResolveNamesInTemplate })); 
                    }
                }
            }
            else 
            {
                DependencyObject contextElement = ContextElement; 
                if (contextElement == null) 
                {
                    // context element has been GC'd, or unavailable (e.g. no mentor) 
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled)
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoDataContext, this); 
                    }
                    return; 
                } 

                object item = contextElement.GetValue(FrameworkElement.DataContextProperty); 

                // if binding inactive or the data item has changed, (re-)activate
                if (Status == BindingStatus.Inactive || !Object.Equals(item, DataItem))
                { 
                    Activate(item);
                } 
            } 
        }
 
        internal void Activate(object item)
        {
            DependencyObject target = TargetElement;
            if (target == null) 
                return;
 
            if (item == DisconnectedItem) 
            {
                // disconnect from the former item, with the least acceptable impact 
                Disconnect();
                return;
            }
 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate);
 
            Deactivate(); 

            if (TraceLog != null) 
                TraceLog.Add("Activate item = {0}", TraceLog.IdFor(item));

            // apply magic (for CVS, DSP, etc.), unless asked not to
            if (!ParentBinding.BindsDirectlyToSource) 
            {
                CollectionViewSource cvs = item as CollectionViewSource; 
                this.CollectionViewSource = cvs; 
                if (cvs != null)
                { 
                    item = cvs.CollectionView;

                    // the CVS is one of our implicit sources
                    ChangeWorkerSources(null, 0); 

                    if (isExtendedTraceEnabled) 
                    { 
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UseCVS( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(cvs)));
                    }
                } 
                else
                { 
                    // when the source is DataSourceProvider, use its data instead 
                    item = DereferenceDataProvider(item);
                } 
            }

            _dataItem = CreateReference(item);
 
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.ActivateItem(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(item)));
            }

            if (Worker == null) 
                CreateWorker();
 
            // mark the BindingExpression active 
            SetStatus(BindingStatus.Active);
 
            // attach to data item (may set error status)
            Worker.AttachDataItem();

            // 

 
            // initial transfer 
            bool initialTransferIsUpdate = IsOneWayToSource;
            object currentValue; 
            if (ShouldUpdateWithCurrentValue(target, out currentValue))
            {
                initialTransferIsUpdate = true;
                ChangeValue(currentValue, /*notify*/false); 
                NeedsUpdate = true;
            } 
 
            if (!initialTransferIsUpdate)
            { 
                ValidationError error;
                object value = GetInitialValue(target, out error);
                if (value != NullDataItem)
                { 
                    TransferValue(value, false);
                } 
 
                if (error != null)
                { 
                    UpdateValidationError(error);
                }
            }
            else if (!IsInMultiBindingExpression)   // MultiBinding initiates its own update 
            {
                UpdateValue(); 
            } 

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831) 
        }

        // return the value for the initial data transfer.  Specifically:
        //      normal case - return UnsetValue (we'll get the value from the source object) 
        //      valid proposed value - return the proposed value
        //      invalid proposed value - two subcases: 
        //          one-way binding - return default/fallback value 
        //          two-way binding - retrun NullDataItem (meaning "don't transfer")
        // 
        //      In both subcases, adopt the validation errors discovered earlier.
        //      In the two-way subcase, instead of a source-to-target transfer, we set the
        //      the target property to the (saved) raw proposed value, as if the user
        //      had edited this property. 
        object GetInitialValue(DependencyObject target, out ValidationError error)
        { 
            object proposedValue; 

            // find the binding group this binding would join if it were two-way (even if it isn't) 
            BindingGroup bindingGroup = RootBindingExpression.FindBindingGroup(true, ContextElement);
            BindingGroup.ProposedValueEntry entry;

            // get the proposed value from the binding group 
            if (bindingGroup == null ||
                (entry = bindingGroup.GetProposedValueEntry(SourceItem, SourcePropertyName)) == null) 
            { 
                // no proposed value
                error = null; 
                proposedValue = DependencyProperty.UnsetValue;
            }
            else
            { 
                // adopt the validation error (possibly null)
                error = entry.ValidationError; 
 
                if (IsReflective && TargetProperty.IsValidValue(entry.RawValue))
                { 
                    // two-way binding - set the target property directly
                    target.SetValue(TargetProperty, entry.RawValue);
                    proposedValue = NullDataItem;
                    bindingGroup.RemoveProposedValueEntry(entry); 
                }
                else if (entry.ConvertedValue == DependencyProperty.UnsetValue) 
                { 
                    // invalid proposed value - use fallback/default
                    proposedValue = UseFallbackValue(); 
                }
                else
                {
                    // valid proposed value 
                    proposedValue = entry.ConvertedValue;
                } 
 
                // if this binding didn't take over responsibility for the proposed
                // value, add it to the list of bindings using the proposed value 
                if (proposedValue != NullDataItem)
                {
                    bindingGroup.AddBindingForProposedValue(this, SourceItem, SourcePropertyName);
                } 
            }
 
            return proposedValue; 
        }
 
        internal override void Deactivate()
        {
            if (TraceLog != null)
                TraceLog.Add("Deactivate"); 

            // inactive BindingExpressions don't need any more work 
            if (Status == BindingStatus.Inactive) 
                return;
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate))
            {
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.Deactivate( 
                                        TraceData.Identify(this)));
            } 
 
            // stop transfers
            CancelPendingTasks(); 

            // detach from data item
            if (Worker != null)
                Worker.DetachDataItem(); 

            // restore default value, in case source/converter fail to provide a good value 
            ChangeValue(DefaultValueObject, false); 

            // don't keep a handle to old data item if the BindingExpression is inactive 
            _dataItem = null;

            SetStatus(BindingStatus.Inactive);
        } 

        // disconnect from the former item, with the least acceptable impact. 
        // This arises when a container is removed from an ItemsControl. 
        internal override void Disconnect()
        { 
            // disconnect this binding from its former item
            _dataItem = CreateReference(DisconnectedItem);

            if (Worker == null) 
                return;
 
            Worker.AttachDataItem(); 

            base.Disconnect(); 
        }

        // if the root item is a DataSourceProvider, use its Data instead
        // and listen for DataChanged events.  (Unless overridden explicitly 
        // by the BindsDirectlyToSource property).
        private object DereferenceDataProvider(object item) 
        { 
            DataSourceProvider dataProvider = item as DataSourceProvider;
            if (dataProvider != _dataProvider) 
            {
                // we have a new data provider - retarget the event handler
                if (_dataProvider != null)
                { 
                    if (TraceLog != null)
                    { 
                        TraceLog.Add("-OnDataChanged to {0}", TraceLog.IdFor(_dataProvider)); 
                    }
                    DataChangedEventManager.RemoveListener(_dataProvider, this); 
                }

                _dataProvider = dataProvider;
 
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate))
                { 
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.UseDataProvider(
                                            TraceData.Identify(this), 
                                            TraceData.Identify(_dataProvider)));
                }

                if (_dataProvider != null) 
                {
                    if (TraceLog != null) 
                    { 
                        TraceLog.Add("+OnDataChanged to {0}", TraceLog.IdFor(_dataProvider));
                    } 
                    DataChangedEventManager.AddListener(_dataProvider, this);
                    _dataProvider.InitialLoad();
                }
            } 

            return (_dataProvider != null) ? _dataProvider.Data : item; 
        } 

#endregion Activation 

#region Worker

        private void CreateWorker() 
        {
            Invariant.Assert(Worker == null, "duplicate call to CreateWorker"); 
 
            _worker = new ClrBindingWorker(this, Engine);
        } 

        // worker calls here if it changes its dependency sources
        // n is the number of real entries in newWorkerSources (which may be longer)
        internal void ChangeWorkerSources(WeakDependencySource[] newWorkerSources, int n) 
        {
            int offset = 0; 
            int size = n; 

            // create the new sources array, and add the context and CollectionViewSource elements 
            DependencyObject contextElement = ContextElement;
            CollectionViewSource cvs = CollectionViewSource;
            bool usesLanguage = UsesLanguage;
 
            if (contextElement != null)
                ++size; 
            if (cvs != null) 
                ++size;
            if (usesLanguage) 
                ++size;

            WeakDependencySource[] newSources = (size > 0) ? new WeakDependencySource[size] : null;
 
            if (contextElement != null)
            { 
                newSources[offset++] = new WeakDependencySource(_ctxElement, FrameworkElement.DataContextProperty); 
            }
 
            if (cvs != null)
            {
                WeakReference wr = _collectionViewSource as WeakReference;
                newSources[offset++] = 
                    (wr != null) ? new WeakDependencySource(wr, CollectionViewSource.ViewProperty)
                                 : new WeakDependencySource(cvs, CollectionViewSource.ViewProperty); 
            } 

            if (usesLanguage) 
            {
                newSources[offset++] = new WeakDependencySource(TargetElementReference, FrameworkElement.LanguageProperty);
            }
 
            // add the worker's sources
            if (n > 0) 
                Array.Copy(newWorkerSources, 0, newSources, offset, n); 

            // tell the property engine 
            ChangeSources(newSources);
        }

#endregion Worker 

#region Value 
 
        // transfer a value from the source to the target
        void TransferValue() 
        {
            TransferValue(DependencyProperty.UnsetValue, false);
        }
 
        // transfer a value from the source to the target
        internal void TransferValue(object newValue, bool isASubPropertyChange) 
        { 
            // if the target element has been GC'd, do nothing
            DependencyObject target = TargetElement; 
            if (target == null)
                return;

            // if the BindingExpression hasn't activated, do nothing 
            if (Worker == null)
                return; 
 
            Type targetType = GetEffectiveTargetType();
            IValueConverter implicitConverter = null; 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Transfer);

            // clear the Pending flag before actually doing the transfer.  That way if another
            // thread sets the flag, we'll schedule another transfer.  This might do more 
            // transfers than absolutely necessary, but it guarantees that we'll eventually pick
            // up the value from the last change. 
            IsTransferPending = false; 
            IsInTransfer = true;
 
            UsingFallbackValue = false;

            // get the raw value from the source
            object value = (newValue == DependencyProperty.UnsetValue) ? Worker.RawValue() : newValue; 

            if (isExtendedTraceEnabled) 
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.GetRawValue( 
                                        TraceData.Identify(this),
                                        TraceData.Identify(value)));
            }
 
            // apply any necessary conversions
            if (value != DependencyProperty.UnsetValue) 
            { 
            #if !TargetNullValueBC  //BreakingChange
                bool doNotSetStatus = false; 
            #endif

                if (!UseDefaultValueConverter)
                { 
                    // if there's a user-defined converter, call it without catching
                    // exceptions (bug 992237).  It can return DependencyProperty.UnsetValue 
                    // to indicate a failure to convert. 
                    value = Converter.Convert(value, targetType, ParentBinding.ConverterParameter, GetCulture());
 
                    if (isExtendedTraceEnabled)
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UserConverter( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(value))); 
                    } 

                    // chain in a default value converter if the returned value's type is not compatible with the targetType 
                    if (   ((value != null) && (value != Binding.DoNothing) && (value != DependencyProperty.UnsetValue))
                        && !targetType.IsAssignableFrom(value.GetType()))
                    {
                        // the dynamic converter is shared between Transfer and Update directions 
                        // once instantiated, DefaultValueConverters are kept in a lookup table, making swapping
                        // default value converters in the DynamicValueConverter reasonably fast 
                        implicitConverter = DynamicConverter; 
                    }
                } 
                else
                {
                    // if there's no user-defined converter, use the default converter (if any)
                    // we chose earlier (in SetupDefaultValueConverter) 
                    implicitConverter = Converter;
                } 
 
                // apply an implicit conversion, if needed.  This can be
                //  a) null conversion 
                //  b) string formatting
                //  c) type conversion
                if ((value != Binding.DoNothing) && (value != DependencyProperty.UnsetValue))
                { 
                    // ultimately, TargetNullValue should get assigned implicitly,
                    // even if the user doesn't declare it.  We can't do this yet because 
                    // of back-compat.  I wrote it both ways, and #if'd out the breaking 
                    // change.
                #if TargetNullValueBC   //BreakingChange 
                    if (IsNullValue(value))
                #else
                    if (EffectiveTargetNullValue != DependencyProperty.UnsetValue &&
                        IsNullValue(value)) 
                #endif
                    { 
                        value = EffectiveTargetNullValue; 

                        if (isExtendedTraceEnabled) 
                        {
                            TraceData.Trace(TraceEventType.Warning,
                                                TraceData.NullConverter(
                                                    TraceData.Identify(this), 
                                                    TraceData.Identify(value)));
                        } 
                    } 
                #if !TargetNullValueBC   //BreakingChange
                    // For DBNull, unless there's a user converter, we handle it here 
                    else if ((value == DBNull.Value) && (Converter == null || UseDefaultValueConverter))
                    {
                        if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        { 
                            value = null;
                        } 
                        else 
                        {
                            value = DependencyProperty.UnsetValue; 
                            // The 3.5 code failed to set the status to UpdateTargetError in this
                            // case.  It's a bug, but we have to maintain the buggy behavior for
                            // back-compat.
                            doNotSetStatus = true; 
                        }
 
                        if (isExtendedTraceEnabled) 
                        {
                            TraceData.Trace(TraceEventType.Warning, 
                                                TraceData.ConvertDBNull(
                                                    TraceData.Identify(this),
                                                    TraceData.Identify(value)));
                        } 

                    } 
                #endif 
                    else if (implicitConverter != null || EffectiveStringFormat != null)
                    { 
                        // call a DefaultValueConverter:
                        // NOTE:
                        // here we pass in the TargetElement that is expected by our default value converters;
                        // this does violate the general rule that value converters should be stateless 
                        // and must not be aware of e.g. their target element.
                        // Our DefaultValueConverters are all internal and only use this target element 
                        // to determine a BaseUri for their TypeConverters 
                        // -> hence a reluctant exeption of above rule
                        value = ConvertHelper(implicitConverter, value, targetType, TargetElement, GetCulture()); 

                        if (isExtendedTraceEnabled)
                        {
                            TraceData.Trace(TraceEventType.Warning, 
                                                TraceData.DefaultConverter(
                                                    TraceData.Identify(this), 
                                                    TraceData.Identify(value))); 
                        }
                    } 
                }

                if (
            #if !TargetNullValueBC   //BreakingChange 
                    !doNotSetStatus &&
            #endif 
                    value == DependencyProperty.UnsetValue) 
                {
                    SetStatus(BindingStatus.UpdateTargetError); 
                }
            }

            // the special value DoNothing means no error, but no data transfer 
            if (value == Binding.DoNothing)
                goto Done; 
 
            // if the value isn't acceptable to the target property, don't use it
            // (in MultiBinding, the value will go through the multi-converter, so 
            // it's too early to make this judgment)
            if (!IsInMultiBindingExpression && value != IgnoreDefaultValue &&
                value != DependencyProperty.UnsetValue && !TargetProperty.IsValidValue(value))
            { 
                if (TraceData.IsEnabled && !IsInBindingExpressionCollection)
                { 
                    TraceData.Trace(TraceLevel, TraceData.BadValueAtTransfer, value, this); 
                }
 
                if (isExtendedTraceEnabled)
                {
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BadValueAtTransferExtended( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(value))); 
                } 

                value = DependencyProperty.UnsetValue; 

                if (Status == BindingStatus.Active)
                    SetStatus(BindingStatus.UpdateTargetError);
            } 

            // If we haven't obtained a value yet, 
            // use the fallback value.  This could happen when the currency 
            // has moved off the end of the collection, e.g.
            if (value == DependencyProperty.UnsetValue) 
            {
                value = UseFallbackValue();

                if (isExtendedTraceEnabled) 
                {
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.UseFallback( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(value))); 
                }
            }

            // Ignore a default source value by setting the value to NoValue; 
            // this causes the property engine to obtain the value elsewhere
            if (value == IgnoreDefaultValue) 
            { 
                value = Expression.NoValue;
            } 

            if (isExtendedTraceEnabled)
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.TransferValue(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(value))); 
            }
 
            // if this is a re-transfer after a source update and the value
            // hasn't changed, don't do any more work.
            if (IsInUpdate && Object.Equals(value, Value))
            { 
                goto Done;
            } 
 
            // update the cached value
            ChangeValue(value, true); 
            Invalidate(isASubPropertyChange);
            OnTargetUpdated();
            ValidateOnTargetUpdated();
 
        Done:
            IsInTransfer = false; 
 
            GC.KeepAlive(target);   // keep target alive during transfer (bug 956831)
        } 

        // run the validation rules marked as ValidateOnTargetUpdated
        private void ValidateOnTargetUpdated()
        { 
            // update the validation state
            ValidationError validationError = null; 
 
            Collection validationRules = ParentBinding.ValidationRulesInternal;
            CultureInfo culture = null; 

            bool needDataErrorRule = ParentBinding.ValidatesOnDataErrors;

            if (validationRules != null) 
            {
                // these may be needed by several rules, but only compute them once 
                object rawValue = DependencyProperty.UnsetValue; 
                object itemValue = DependencyProperty.UnsetValue;
 
                foreach (ValidationRule validationRule in validationRules)
                {
                    if (validationRule.ValidatesOnTargetUpdated)
                    { 
                        if (validationRule is DataErrorValidationRule)
                        { 
                            needDataErrorRule = false; 
                        }
 
                        object value;

                        switch (validationRule.ValidationStep)
                        { 
                            case ValidationStep.RawProposedValue:
                                if (rawValue == DependencyProperty.UnsetValue) 
                                { 
                                    rawValue = GetRawProposedValue();
                                } 
                                value = rawValue;
                                break;
                            case ValidationStep.ConvertedProposedValue:
                                if (itemValue == DependencyProperty.UnsetValue) 
                                {
                                    itemValue = Worker.RawValue(); 
                                } 
                                value = itemValue;
                                break; 
                            case ValidationStep.UpdatedValue:
                            case ValidationStep.CommittedValue:
                                value = this;
                                break; 
                            default:
                                throw new InvalidOperationException(SR.Get(SRID.ValidationRule_UnknownStep, validationRule.ValidationStep, validationRule)); 
                        } 

                        // lazy-fetch culture (avoids exception when target DP is Language) 
                        if (culture == null)
                        {
                            culture = GetCulture();
                        } 

                        validationError = RunValidationRule(validationRule, value, culture); 
                        if (validationError != null) 
                            break;
                    } 
                }
            }

            if (needDataErrorRule && validationError == null) 
            {
                // lazy-fetch culture (avoids exception when target DP is Language) 
                if (culture == null) 
                {
                    culture = GetCulture(); 
                }

                validationError = RunValidationRule(DataErrorValidationRule.Instance, this, culture);
            } 

            UpdateValidationError(validationError); 
        } 

        ValidationError RunValidationRule(ValidationRule validationRule, object value, CultureInfo culture) 
        {
            ValidationError error;

            ValidationResult validationResult = validationRule.Validate(value, culture); 

            if (validationResult.IsValid) 
            { 
                error = null;
            } 
            else
            {
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update))
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.ValidationRuleFailed( 
                                            TraceData.Identify(this), 
                                            TraceData.Identify(validationRule)));
                } 

                error = new ValidationError(validationRule, this, validationResult.ErrorContent, null);
            }
 
            return error;
        } 
 
        private object ConvertHelper(IValueConverter converter, object value, Type targetType, object parameter, CultureInfo culture)
        { 
            // use the StringFormat (if appropriate) in preference to the default converter
            string stringFormat = EffectiveStringFormat;
            Invariant.Assert(converter != null || stringFormat != null);
 
            // PreSharp uses message numbers that the C# compiler doesn't know about.
            // Disable the C# complaints, per the PreSharp documentation. 
            #pragma warning disable 1634, 1691 

            // PreSharp complains about catching NullReference (and other) exceptions. 
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly.
            #pragma warning disable 56500

            object convertedValue = null; 
            try
            { 
                if (stringFormat != null) 
                {
                    convertedValue = String.Format(culture, stringFormat, value); 
                }
                else
                {
                    convertedValue = converter.Convert(value, targetType, parameter, culture); 
                }
            } 
 
            // Catch all exceptions.  There is no app code on the stack,
            // so the exception isn't actionable by the app. 
            // Yet we don't want to crash the app.
            catch (Exception ex)
            {
                // the DefaultValueConverter can end up calling BaseUriHelper.GetBaseUri() 
                // which can raise SecurityException if the app does not have the right FileIO privileges
                if (CriticalExceptions.IsCriticalApplicationException(ex)) 
                    throw; 

                if (TraceData.IsEnabled) 
                {
                    string name = String.IsNullOrEmpty(stringFormat) ? converter.GetType().Name : "StringFormat";
                    TraceData.Trace(TraceLevel,
                            TraceData.BadConverterForTransfer( 
                                name,
                                AvTrace.ToStringHelper(value), 
                                AvTrace.TypeName(value)), 
                            this, ex);
                } 
                convertedValue = DependencyProperty.UnsetValue;
            }
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled)
                { 
                    TraceData.Trace(TraceLevel, 
                            TraceData.BadConverterForTransfer(
                                converter.GetType().Name, 
                                AvTrace.ToStringHelper(value),
                                AvTrace.TypeName(value)),
                            this);
                } 
                convertedValue = DependencyProperty.UnsetValue;
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            return convertedValue;
        }
 
        private object ConvertBackHelper(IValueConverter converter,
                                         object value, 
                                         Type sourceType, 
                                         object parameter,
                                         CultureInfo culture) 
        {
            Invariant.Assert(converter != null);

            // PreSharp uses message numbers that the C# compiler doesn't know about. 
            // Disable the C# complaints, per the PreSharp documentation.
            #pragma warning disable 1634, 1691 
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly. 
            #pragma warning disable 56500

            object convertedValue = null;
            try 
            {
                convertedValue = converter.ConvertBack(value, sourceType, parameter, culture); 
            } 

            // Catch all exceptions.  There is no app code on the stack, 
            // so the exception isn't actionable by the app.
            // Yet we don't want to crash the app.
            catch (Exception ex)
            { 
                // the DefaultValueConverter can end up calling BaseUriHelper.GetBaseUri()
                // which can raise SecurityException if the app does not have the right FileIO privileges 
                ex = CriticalExceptions.Unwrap(ex); 
                if (CriticalExceptions.IsCriticalApplicationException(ex))
                    throw; 

                if (TraceData.IsEnabled)
                {
                    TraceData.Trace(TraceEventType.Error, 
                        TraceData.BadConverterForUpdate(
                            AvTrace.ToStringHelper(Value), 
                            AvTrace.TypeName(value)), 
                        this, ex);
                } 

                ProcessException(ex, ValidatesOnExceptions);
                convertedValue = DependencyProperty.UnsetValue;
            } 
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error, 
                        TraceData.BadConverterForUpdate(
                            AvTrace.ToStringHelper(Value),
                            AvTrace.TypeName(value)),
                        this); 
                }
                convertedValue = DependencyProperty.UnsetValue; 
            } 

            #pragma warning restore 56500 
            #pragma warning restore 1634, 1691

            return convertedValue;
        } 

        internal void ScheduleTransfer(bool isASubPropertyChange) 
        { 
            if (isASubPropertyChange && Converter != null)
            { 
                // a converter doesn't care about sub-property changes
                isASubPropertyChange = false;
            }
 
            TransferValue(DependencyProperty.UnsetValue, isASubPropertyChange);
        } 
 

        void OnTargetUpdated() 
        {
            if (NotifyOnTargetUpdated)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                { 
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression 
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression)    // in ProrityBinding, and either active 
                            ||  (IsAttaching && (Status==BindingStatus.Active || UsingFallbackValue) // or about to become active
                            )
                        )
                    { 
                        // while attaching a normal (not style-defined) BindingExpression,
                        // we must defer raising the event until after the 
                        // property has been invalidated, so that the event handler 
                        // gets the right value if it asks (bug 1036862)
                        if (IsAttaching && RootBindingExpression == target.ReadLocalValue(TargetProperty)) 
                        {
                            Engine.AddTask(this, TaskOps.RaiseTargetUpdatedEvent);
                        }
                        else 
                        {
                            OnTargetUpdated(target, TargetProperty); 
                        } 
                    }
                } 
            }
        }

        void OnSourceUpdated() 
        {
            if (NotifyOnSourceUpdated) 
            { 
                DependencyObject target = TargetElement;
                if (target != null) 
                {
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression))   // not an inactive BindingExpression 
                    {
                        OnSourceUpdated(target, TargetProperty); 
                    } 
                }
            } 
        }


        // transfer a value from target to source 
        internal override void Update(bool synchronous)
        { 
            // various reasons not to update: 
            if (   !NeedsUpdate                     // nothing to do
                || !IsReflective                    // no update desired 
                || IsInTransfer                     // in a transfer
                || Worker == null                   // not activated
                || !Worker.CanUpdate                // no source (currency moved off end)
                ) 
                return;
 
            if (synchronous) 
            {
                UpdateValue(); 
            }
            else
            {
                Engine.AddTask(this, TaskOps.UpdateValue); 
            }
        } 
 
        internal override object ConvertProposedValue(object value)
        { 
            object rawValue = value;
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update);
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.UpdateRawValue( 
                                        TraceData.Identify(this), 
                                        TraceData.Identify(value)));
            } 

            Type sourceType = Worker.SourcePropertyType;
            IValueConverter implicitConverter = null;
            CultureInfo culture = GetCulture(); 

            // apply user-defined converter 
            if (Converter != null) 
            {
                if (!UseDefaultValueConverter) 
                {
                    // if there's a user-defined converter, call it without catching
                    // exceptions (bug 992237).  It can return DependencyProperty.UnsetValue
                    // to indicate a failure to convert. 
                    value = Converter.ConvertBack(value, sourceType, ParentBinding.ConverterParameter, culture);
 
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.UserConvertBack(
                                                TraceData.Identify(this),
                                                TraceData.Identify(value)));
                    } 

                    // chain in a default value converter if the returned value's type is not compatible with the sourceType 
                    if (value != Binding.DoNothing && value != DependencyProperty.UnsetValue && 
                        !IsValidValueForUpdate(value, sourceType))
                    { 
                        // the dynamic converter is shared between Transfer and Update directions
                        // once instantiated, DefaultValueConverters are kept in a lookup table, making swapping
                        // default value converters reasonably fast
                        implicitConverter = DynamicConverter; 
                    }
                } 
                else 
                {
                    implicitConverter = Converter; 
                }
            }

            // apply an implicit conversion, if needed.  This can be 
            //  a) null conversion
            //  b) type conversion 
            if (value != Binding.DoNothing && value != DependencyProperty.UnsetValue) 
            {
                if (IsNullValue(value)) 
                {
                    if (Worker.IsDBNullValidForUpdate)
                    {
                        value = DBNull.Value; 
                    }
                    else 
                    { 
                        value = NullValueForType(sourceType);
                    } 
                }
                else if (implicitConverter != null)
                {
                    // here we pass in the TargetElement, see NOTE of caution in TransferValue() why this is ok 
                    value = ConvertBackHelper(implicitConverter, value, sourceType, this.TargetElement, culture);
 
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.DefaultConvertBack(
                                                TraceData.Identify(this),
                                                TraceData.Identify(value)));
                    } 
                }
            } 
 
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.Update(
                                        TraceData.Identify(this),
                                        TraceData.Identify(value))); 
            }
 
            // if the conversion failed, signal a validation error 
            if (value == DependencyProperty.UnsetValue)
            { 
                if (ValidationError == null)
                {
                    ValidationError validationError = new ValidationError(ConversionValidationRule.Instance, this, SR.Get(SRID.Validation_ConversionFailed, rawValue), null);
                    UpdateValidationError(validationError); 
                }
            } 
 
            return value;
        } 

        /// 
        /// Get the converted proposed value and inform the binding group
        ///  
        internal override bool ObtainConvertedProposedValue(BindingGroup bindingGroup)
        { 
            bool result = true; 
            object value;
 
            if (NeedsUpdate)
            {
                value = bindingGroup.GetValue(this);
                if (value != DependencyProperty.UnsetValue) 
                {
                    value = ConvertProposedValue(value); 
                    if (value == DependencyProperty.UnsetValue) 
                    {
                        result = false; 
                    }
                }
            }
            else 
            {
                value = BindingGroup.DeferredSourceValue; 
            } 

            bindingGroup.SetValue(this, value); 
            return result;
        }

        internal override object UpdateSource(object value) 
        {
            // If there is a failure to convert, then Update failed. 
            if (value == DependencyProperty.UnsetValue) 
            {
                SetStatus(BindingStatus.UpdateSourceError); 
            }

            if (value == Binding.DoNothing || value == DependencyProperty.UnsetValue ||
                ShouldIgnoreUpdate()) 
            {
                return value; 
            } 

 
            // PreSharp uses message numbers that the C# compiler doesn't know about.
            // Disable the C# complaints, per the PreSharp documentation.
            #pragma warning disable 1634, 1691
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly. 
            #pragma warning disable 56500 

            try 
            {
                BeginSourceUpdate();
                Worker.UpdateValue(value);
            } 

            // Catch all exceptions.  There is no app code on the stack, 
            // so the exception isn't actionable by the app. 
            // Yet we don't want to crash the app.
            catch (Exception ex) 
            {
                ex = CriticalExceptions.Unwrap(ex);
                if (CriticalExceptions.IsCriticalApplicationException(ex))
                    throw; 

                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this, ex); 

                ProcessException(ex, (ValidatesOnExceptions || BindingGroup != null)); 
                SetStatus(BindingStatus.UpdateSourceError);
                value = DependencyProperty.UnsetValue;
            }
            catch // non CLS compliant exception 
            {
                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this); 

                SetStatus(BindingStatus.UpdateSourceError); 
                value = DependencyProperty.UnsetValue;
            }
            finally
            { 
                EndSourceUpdate();
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            OnSourceUpdated();

            return value; 
        }
 
        ///  
        /// Update the source value and inform the binding group
        ///  
        internal override bool UpdateSource(BindingGroup bindingGroup)
        {
            bool result = true;
            if (NeedsUpdate) 
            {
                object value = bindingGroup.GetValue(this); 
                value = UpdateSource(value); 
                bindingGroup.SetValue(this, value);
                if (value == DependencyProperty.UnsetValue) 
                {
                    result = false;
                }
            } 
            return result;
        } 
 
        /// 
        /// Store the value in the binding group 
        /// 
        internal override void StoreValueInBindingGroup(object value, BindingGroup bindingGroup)
        {
            bindingGroup.SetValue(this, value); 
        }
 
        ///  
        /// Run validation rules for the given step
        ///  
        internal override bool Validate(object value, ValidationStep validationStep)
        {
            // run rules attached to this binding
            bool result = base.Validate(value, validationStep); 

            if (validationStep == ValidationStep.UpdatedValue) 
            { 
                if (result && ParentBinding.ValidatesOnDataErrors)
                { 
                    // remember the old validation error, if it came from the implicit DataError rule
                    ValidationError oldValidationError = GetValidationErrors(validationStep);
                    if (oldValidationError != null &&
                        oldValidationError.RuleInError != DataErrorValidationRule.Instance) 
                    {
                        oldValidationError = null; 
                    } 

                    // run the DataError rule, even though it doesn't appear in the 
                    // ValidationRules collection
                    ValidationError error = RunValidationRule(DataErrorValidationRule.Instance, this, GetCulture());

                    if (error != null) 
                    {
                        UpdateValidationError(error); 
                        result = false; 
                    }
                    else if (oldValidationError != null) 
                    {
                        // the implicit rule is now valid - clear the old error
                        UpdateValidationError(null);
                    } 
                }
            } 
            else if (validationStep == ValidationStep.CommittedValue) 
            {
                if (result) 
                {
                    NeedsValidation = false;
                }
            } 

            return result; 
        } 

        ///  
        /// Run validation rules for the given step, and inform the binding group
        /// 
        internal override bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep)
        { 
            if (!NeedsValidation)
                return true; 
 
            object value;
            switch (validationStep) 
            {
                case ValidationStep.RawProposedValue:
                    value = GetRawProposedValue();
                    break; 
                case ValidationStep.ConvertedProposedValue:
                    value = bindingGroup.GetValue(this); 
                    break; 
                case ValidationStep.UpdatedValue:
                case ValidationStep.CommittedValue: 
                    value = this;
                    break;
                default:
                    throw new InvalidOperationException(SR.Get(SRID.ValidationRule_UnknownStep, validationStep, bindingGroup)); 
            }
 
            return Validate(value, validationStep); 
        }
 
        /// 
        /// Get the proposed value(s) that would be written to the source(s), applying
        /// conversion and checking UI-side validation rules.
        ///  
        internal override bool ValidateAndConvertProposedValue(out Collection values)
        { 
            Debug.Assert(NeedsValidation, "check NeedsValidation before calling this"); 
            values = null;
 
            // validate raw proposed value
            object rawValue = GetRawProposedValue();

            bool isValid = Validate(rawValue, ValidationStep.RawProposedValue); 

            // apply conversion and validate it 
            object convertedValue = isValid ? ConvertProposedValue(rawValue) 
                                            : DependencyProperty.UnsetValue;
 
            if (convertedValue == Binding.DoNothing)
            {
                convertedValue = DependencyProperty.UnsetValue;
            } 
            else if (convertedValue == DependencyProperty.UnsetValue)
            { 
                isValid = false; 
            }
            else 
            {
                isValid = Validate(convertedValue, ValidationStep.ConvertedProposedValue);
            }
 
            // return the result
            values = new Collection(); 
            values.Add(new ProposedValue(this, rawValue, convertedValue)); 
            return isValid;
        } 

        private bool IsValidValueForUpdate(object value, Type sourceType)
        {
            // null is always valid, even for value types.  The reflection layer 
            // apparently converts null to default(T).
            if (value == null) 
                return true; 

            // if direct assignment is possible, the value is valid 
            if (sourceType.IsAssignableFrom(value.GetType()))
                return true;

            // if the value is DBNull, ask the worker (answer depends on several factors) 
            if (Convert.IsDBNull(value))
                return Worker.IsDBNullValidForUpdate; 
 
            // otherwise the value is invalid
            return false; 
        }

        private void ProcessException(Exception ex, bool validate)
        { 
            object filteredException = null;
            ValidationError validationError = null; 
 
            // If there is not ExceptionFilter, then Wrap the
            // exception in a ValidationError. 
            if (ExceptionFilterExists())
            {
                filteredException = CallDoFilterException(ex);
 
                if (filteredException == null)
                    return; 
 
                validationError = filteredException as ValidationError;
            } 

            // See if an ExceptionValidationRule is in effect
            if (validationError == null && validate)
            { 
                ValidationRule exceptionValidationRule = ExceptionValidationRule.Instance;
 
                if (filteredException == null) 
                {
                    validationError = new ValidationError(exceptionValidationRule, this, ex.Message, ex); 
                }
                else
                {
                    validationError = new ValidationError(exceptionValidationRule, this, filteredException, ex); 
                }
            } 
 
            if (validationError != null)
            { 
                UpdateValidationError(validationError);
            }
        }
 
        // Sometimes a source update gets requested as a result of event leapfrogging,
        // where the binding has not yet been informed of a pending change to its 
        // path (e.g. Dev10 445406).  In this case, we should simply ignore the update. 
        private bool ShouldIgnoreUpdate()
        { 
            // The detection algorithm below is expensive, so only do when the target
            // property is especially susceptible to the problem
            if (TargetProperty.OwnerType != typeof(System.Windows.Controls.Primitives.Selector) &&  // SelectedItem, SelectedValue, SelectedIndex, etc.
                TargetProperty != ComboBox.TextProperty                                             // ComboBox.Text 
                )
            { 
                return false; 
            }
 
            // Re-evaluate the entire path.  If it doesn't produce the same source
            // object as our cached value, there is presumably a change notification
            // somewhere along the path that hasn't been delivered yet, due to event
            // leapfrogging. 

            // get initial (top-level) item 
            object item; 
            DependencyObject contextElement = ContextElement;
            if (contextElement == null) 
            {
                DependencyObject target = TargetElement;
                if (target != null && UsingMentor)
                { 
                    target = Helper.FindMentor(target);
                } 
                if (target == null) 
                {
                    return true; 
                }
                item = ParentBinding.SourceReference.GetDataObject(target,
                                                    new ObjectRefArgs() { ResolveNamesInTemplate = ResolveNamesInTemplate });
            } 
            else
            { 
                item = contextElement.GetValue(FrameworkElement.DataContextProperty); 
            }
 
            // Apply auto-magic rules for CVS, DSP, etc.
            // This logic should agree with Activate(item), except for event hookup.
            if (!ParentBinding.BindsDirectlyToSource)
            { 
                CollectionViewSource cvs;
                DataSourceProvider dsp; 
 
                if ((cvs = item as CollectionViewSource) != null)
                { 
                    item = cvs.CollectionView;
                }
                else if ((dsp = item as DataSourceProvider) != null)
                { 
                    item = dsp.Data;
                } 
            } 

            // If the top-level item is different, ignore the update 
            if (!Object.Equals(DataItem, item))
                return true;

            // check the rest of the path 
            return !Worker.IsPathCurrent();
        } 
#endregion Value 

#region Event handlers 

        private void OnDataContextChanged(DependencyObject contextElement)
        {
            // ADO BindingExpressions change the data context when a field changes. 
            // If the field is the one we're updating, ignore the DC change.
            if (!IsInUpdate && CanActivate) 
            { 
                if (IsReflective && RootBindingExpression.ParentBindingBase.BindingGroupName == String.Empty)
                { 
                    RejoinBindingGroup(IsReflective, contextElement);
                }

                object newItem = contextElement.GetValue(FrameworkElement.DataContextProperty); 
                if (!Object.Equals(DataItem, newItem))
                { 
                    Activate(newItem); 
                }
            } 
        }

        /// 
        /// Handle events from the centralized event table 
        /// 
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        { 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.GotEvent(
                                        TraceData.Identify(this),
                                        TraceData.IdentifyWeakEvent(managerType), 
                                        TraceData.Identify(sender)));
            } 
 
            if (managerType == typeof(CurrentChangingEventManager))
            { 
                Update(true);
                //
            }
            else if (managerType == typeof(CurrentChangedEventManager)) 
            {
                Worker.OnCurrentChanged(sender as ICollectionView, e); 
            } 
            else if (managerType == typeof(DataChangedEventManager))
            { 
                if (TraceLog != null)
                {
                    TraceLog.Add(" OnDataChanged from {0} at {1}", TraceLog.IdFor(_dataProvider), TraceLog.IdFor(this));
                } 
                Activate(sender);
            } 
            else if (managerType == typeof(LostFocusEventManager)) 
            {
                Update(true); 
            }
            else if (managerType == typeof(InheritanceContextChangedEventManager))
            {
                if (Status == BindingStatus.Unattached) 
                {
                    // retry bindings immediately when InheritanceContext changes, 
                    // so that triggers, animations, and rendering see the bound 
                    // value when they initialize their own local cache (bug DD 139838).
                    AttachToContext(AttachAttempt.Again); 
                    if (Status != BindingStatus.Unattached)
                    {
                        // if that worked, we don't need to run the task again
                        Engine.CancelTask(this, TaskOps.AttachToContext); 
                    }
                } 
                else 
                {
                    AttachToContext(AttachAttempt.Last); 
                }
            }
            else
            { 
                return false;       // unrecognized event
            } 
 
            return true;
        } 

#endregion Event handlers

#region Helper functions 

 
        // 
        // If this BindingExpression's ParentBinding has an ExceptionFilter set,
        // call it, otherwise give the MultiBinding (if there is one) 
        // a chance.
        //
        private object CallDoFilterException(Exception ex)
        { 
            if (ParentBinding.UpdateSourceExceptionFilter != null)
            { 
                return ParentBinding.DoFilterException(this, ex); 
            }
            else if (IsInMultiBindingExpression) 
            {
                return ParentMultiBindingExpression.ParentMultiBinding.DoFilterException(this, ex);
            }
 
            return null;
        } 
 
        private bool ExceptionFilterExists()
        { 
            return ( (ParentBinding.UpdateSourceExceptionFilter != null) ||
                     (IsInMultiBindingExpression && ParentMultiBindingExpression.ParentMultiBinding.UpdateSourceExceptionFilter != null)
                   );
        } 

 
        // surround any code that changes the value of a BindingExpression by 
        //      using (bindExpr.ChangingValue())
        //      { ... } 
        internal IDisposable ChangingValue()
        {
            return new ChangingValueHelper(this);
        } 

        // cancel any pending work 
        internal void CancelPendingTasks() 
        {
            Engine.CancelTasks(this); 
        }

        // replace this BindingExpression with a new one
        void Replace() 
        {
            DependencyObject target = TargetElement; 
            if (target != null) 
            {
                if (IsInBindingExpressionCollection) 
                    ParentBindingExpressionBase.ReplaceChild(this);
                else
                    BindingOperations.SetBinding(target, TargetProperty, ParentBinding);
            } 
        }
 
        // raise the TargetUpdated event (explicit polymorphism) 
        internal static void OnTargetUpdated(DependencyObject d, DependencyProperty dp)
        { 
            DataTransferEventArgs args = new DataTransferEventArgs(d, dp);
            args.RoutedEvent = Binding.TargetUpdatedEvent;
            FrameworkObject fo = new FrameworkObject(d);
 
            if (!fo.IsValid && d != null)
            { 
                fo.Reset(Helper.FindMentor(d)); 
            }
 
            fo.RaiseEvent(args);
        }

        // raise the SourceUpdatedEvent event (explicit polymorphism) 
        internal static void OnSourceUpdated(DependencyObject d, DependencyProperty dp)
        { 
            DataTransferEventArgs args = new DataTransferEventArgs(d, dp); 
            args.RoutedEvent = Binding.SourceUpdatedEvent;
            FrameworkObject fo = new FrameworkObject(d); 

            if (!fo.IsValid && d != null)
            {
                fo.Reset(Helper.FindMentor(d)); 
            }
 
            fo.RaiseEvent(args); 
        }
 
        internal override void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            DependencyProperty dp = args.Property;
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
            { 
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.GotPropertyChanged(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(d),
                                        dp.Name));
            }
 
            if (dp == FrameworkElement.DataContextProperty)
            { 
                DependencyObject contextElement = ContextElement; 
                if (d == contextElement)
                { 
                    OnDataContextChanged(contextElement);
                }
            }
 
            if (dp == CollectionViewSource.ViewProperty)
            { 
                CollectionViewSource cvs = this.CollectionViewSource; 
                if (d == cvs)
                { 
                    Activate(cvs);
                }
            }
 
            if (dp == FrameworkElement.LanguageProperty && UsesLanguage && d == TargetElement)
            { 
                InvalidateCulture(); 
            }
 
            if (Worker != null)
            {
                Worker.OnSourceInvalidation(d, dp, args.IsASubPropertyChange);
            } 
        }
 
 
        private class ChangingValueHelper : IDisposable
        { 
            internal ChangingValueHelper(BindingExpression b)
            {
                _bindingExpression = b;
                b.CancelPendingTasks(); 
            }
 
            public void Dispose() 
            {
                _bindingExpression.TransferValue(); 
                GC.SuppressFinalize(this);
            }

            BindingExpression _bindingExpression; 
        }
 
        void SetDataItem(object newItem) 
        {
            _dataItem = CreateReference(newItem); 
        }

        // find the DataSource object (if any) that produced the DataContext
        // for element d 
        object GetDataSourceForDataContext(DependencyObject d)
        { 
            // look for ancestor that contributed the inherited value 
            DependencyObject ancestor;
            BindingExpression b = null; 

            for (ancestor = d;
                 ancestor != null;
                 ancestor = FrameworkElement.GetFrameworkParent(ancestor)) 
            {
                if (HasLocalDataContext(ancestor)) 
                { 
                    b = BindingOperations.GetBindingExpression(ancestor, FrameworkElement.DataContextProperty) as BindingExpression;
                    break; 
                }
            }

            if (b != null) 
                return b.DataSource;
 
            return null; 
        }
 
#endregion Helper functions

        //------------------------------------------------------
        // 
        //  Private Fields
        // 
        //----------------------------------------------------- 

        WeakReference           _ctxElement; 
        object                  _dataItem;
        BindingWorker           _worker;
        IValueConverter         _valueConverter;
        Type                    _sourceType; 
        DataSourceProvider      _dataProvider;
        object                  _collectionViewSource; 
        DynamicValueConverter   _dynamicConverter; 

        internal static readonly object NullDataItem = new NamedObject("NullDataItem"); 
        internal static readonly object IgnoreDefaultValue = new NamedObject("IgnoreDefaultValue");
    }

} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Defines BindingExpression object, the run-time instance of data binding. 
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
// 
//---------------------------------------------------------------------------

using System;
using System.Collections; 
using System.Collections.Generic;
using System.Collections.ObjectModel; 
using System.Diagnostics; 
using System.ComponentModel;
using System.Globalization; 
using System.Windows.Threading;
using System.Threading;
using System.Xml;
using System.Windows; 
using System.Windows.Input;
using System.Windows.Controls; 
using System.Windows.Markup; 
using MS.Utility;
using MS.Internal; 
using MS.Internal.Controls; // Validation
using MS.Internal.Data;
using MS.Internal.KnownBoxes;
using MS.Internal.Utility;  // TraceLog 

namespace System.Windows.Data 
{ 

 
    /// 
    /// called whenever any exception is encountered when trying to update
    /// the value to the source. The application author can provide its own
    /// handler for handling exceptions here. If the delegate returns 
    ///     null - dont throw an error or provide a ValidationError.
    ///     Exception - returns the exception itself, we will fire the exception using Async exception model. 
    ///     ValidationError - it will set itself as the BindingInError and add it to the elements Validation errors. 
    /// 
    public delegate object UpdateSourceExceptionFilterCallback(object bindExpression, Exception exception); 

    /// 
    ///  Describes a single run-time instance of data binding, binding a target
    ///  (element, DependencyProperty) to a source (object, property, XML node) 
    /// 
    public sealed class BindingExpression : BindingExpressionBase, IDataBindEngineClient, IWeakEventListener 
    { 
        //-----------------------------------------------------
        // 
        //  Enums
        //
        //-----------------------------------------------------
 
        internal enum SourceType { Unknown, CLR, XML }
        private enum AttachAttempt { First, Again, Last } 
 
        //------------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        private BindingExpression(Binding binding, BindingExpressionBase owner)
            : base(binding, owner) 
        { 
            UseDefaultValueConverter = (ParentBinding.Converter == null);
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ShowPath))
            {
                PropertyPath pp = binding.Path;
                string path = (pp != null) ? pp.Path : String.Empty; 

                if (String.IsNullOrEmpty(binding.XPath)) 
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BindingPath( 
                                            TraceData.Identify(path)));
                }
                else
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BindingXPathAndPath( 
                                            TraceData.Identify(binding.XPath), 
                                            TraceData.Identify(path)));
                } 
            }
        }

        //------------------------------------------------------ 
        //
        //  Interfaces 
        // 
        //------------------------------------------------------
 
        void IDataBindEngineClient.TransferValue()
        {
            TransferValue();
        } 

        void IDataBindEngineClient.UpdateValue() 
        { 
            UpdateValue();
        } 

        bool IDataBindEngineClient.AttachToContext(bool lastChance)
        {
            AttachToContext(lastChance ? AttachAttempt.Last : AttachAttempt.Again); 
            return (Status != BindingStatus.Unattached);
        } 
 
        void IDataBindEngineClient.VerifySourceReference(bool lastChance)
        { 
            DependencyObject target = TargetElement;
            ObjectRef sourceRef = ParentBinding.SourceReference;
            DependencyObject mentor = !UsingMentor ? target : Helper.FindMentor(target);
            ObjectRefArgs args = new ObjectRefArgs() { 
                                    ResolveNamesInTemplate = ResolveNamesInTemplate,
                                    }; 
            object source = sourceRef.GetDataObject(mentor, args); 

            if (source != DataItem) 
            {
                // the source reference resolves differently from before, so
                // re-attach to the tree context
                AttachToContext(lastChance ? AttachAttempt.Last : AttachAttempt.Again); 
            }
        } 
 
        void IDataBindEngineClient.OnTargetUpdated()
        { 
            OnTargetUpdated();
        }

        DependencyObject IDataBindEngineClient.TargetElement 
        {
            get { return TargetElement; } 
        } 

        //----------------------------------------------------- 
        //
        //  Public Properties
        //
        //------------------------------------------------------ 

        ///  Binding from which this expression was created  
        public Binding ParentBinding { get { return (Binding)ParentBindingBase; } } 

        /// The data item actually used by this BindingExpression 
        public object DataItem { get { return GetReference(_dataItem); } }

        /// The data source actually used by this BindingExpression
        internal object DataSource 
        {
            get 
            { 
                DependencyObject target = TargetElement;
                if (target == null) 
                    return null;

                // if we're using DataContext, find the source for the DataContext
                if (_ctxElement != null) 
                    return GetDataSourceForDataContext(ContextElement);
 
                // otherwise use the explicit source 
                ObjectRef or = ParentBinding.SourceReference;
                return or.GetObject(target, new ObjectRefArgs()); 
            }
        }

        //----------------------------------------------------- 
        //
        //  Public Methods 
        // 
        //-----------------------------------------------------
 
        ///  Send the current value back to the source 
        ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource 
        public override void UpdateSource()
        { 
            if (Status == BindingStatus.Detached)
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionIsDetached)); 
 
            NeedsUpdate = true;     // force update
            Update(true);           // update synchronously 
        }

        ///  Force a data transfer from source to target 
        public override void UpdateTarget() 
        {
            if (Status == BindingStatus.Detached) 
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionIsDetached)); 

            if (Worker != null) 
            {
                Worker.RefreshValue();  // calls TransferValue
            }
        } 

#region Expression overrides 
 
        /// 
        ///     Called to evaluate the Expression value 
        /// 
        /// DependencyObject being queried
        /// Property being queried
        /// Computed value. Default (of the target) if unavailable. 
        internal override object GetValue(DependencyObject d, DependencyProperty dp)
        { 
            return Value; 
        }
 
        /// 
        ///     Allows Expression to store set values
        /// 
        /// DependencyObject being set 
        /// Property being set
        /// Value being set 
        /// true if Expression handled storing of the value 
        internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value)
        { 
            if (IsReflective)
            {
                Value = value;
                return true; 
            }
            else 
            { 
                // if the binding doesn't push values back to the source, allow
                // SetValue to overwrite the binding with a local value 
                return false;
            }
        }
 
        /// 
        ///     Notification that a Dependent that this Expression established has 
        ///     been invalidated as a result of a Source invalidation 
        /// 
        /// DependencyObject that was invalidated 
        /// Changed event args for the property that was invalidated
        internal override void OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            if (d == null) 
                throw new ArgumentNullException("d");
            if (args == null) 
                throw new ArgumentNullException("args"); 

            DependencyProperty dp = args.Property; 
            if (dp == null)
                throw new InvalidOperationException(SR.Get(SRID.ArgumentPropertyMustNotBeNull, "Property", "args"));

            // ignore irrelevant notifications.  This test must happen before any marshalling. 
            bool relevant = !IgnoreSourcePropertyChange;
 
            if (dp == FrameworkElement.DataContextProperty && d == ContextElement) 
            {
                relevant = true;    // changes from context element are always relevant 
            }
            else if (dp == CollectionViewSource.ViewProperty && d == CollectionViewSource)
            {
                relevant = true;    // changes from the CollectionViewSource are always relevant 
            }
            else if (dp == FrameworkElement.LanguageProperty && UsesLanguage && d == TargetElement) 
            { 
                relevant = true;    // changes from target's Language are always relevant
            } 
            else if (relevant)
            {
                relevant = (Worker != null) && (Worker.UsesDependencyProperty(d, dp));
            } 

            if (!relevant) 
                return; 

            base.OnPropertyInvalidation(d, args); 
        }

#endregion  Expression overrides
 
        //-----------------------------------------------------
        // 
        //  Protected Methods 
        //
        //------------------------------------------------------ 

        /// 
        /// Invalidate the given child expression.
        ///  
        internal override void InvalidateChild(BindingExpressionBase bindingExpression)
        { 
            // BindingExpression does not support child bindings 
        }
 
        /// 
        /// Change the dependency sources for the given child expression.
        /// 
        internal override void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources) 
        {
            // BindingExpression does not support child bindings 
        } 

        ///  
        /// Replace the given child expression with a new one.
        /// 
        internal override void ReplaceChild(BindingExpressionBase bindingExpression)
        { 
            // BindingExpression does not support child bindings
        } 
 
        // register the leaf bindings with the binding group
        internal override void UpdateBindingGroup(BindingGroup bg) 
        {
            bg.UpdateTable(this);
        }
 
        //-----------------------------------------------------
        // 
        //  Internal Properties 
        //
        //------------------------------------------------------ 

        // The ContextElement is the DependencyObject (if any) whose DataContext
        // is used as the starting point for the evaluation of the BindingExpression Path.
        //      We should not store a strong reference to the context element, 
        // for the same reasons as mentioned above for TargetElement.  Instead,
        // we store a weak reference.  Callers should be prepared for the case 
        // ContextElement==null, which is different from _ctxElement==null.  The 
        // former means the BindingExpression uses a context element, but that element has
        // been GC'd;  the latter means that the BindingExpression does not use a context 
        // element.
        internal DependencyObject ContextElement
        {
            get 
            {
                if (_ctxElement != null) 
                    return _ctxElement.Target as DependencyObject; 
                else
                    return null; 
            }
        }

        // The CollectionViewSource is the source object, as a CollectionViewSource. 
        internal CollectionViewSource CollectionViewSource
        { 
            get { return (CollectionViewSource)GetReference(_collectionViewSource); } 
            set { _collectionViewSource = CreateReference(value); }
        } 

        ///  True if this binding expression should ignore changes from the source 
        internal bool IgnoreSourcePropertyChange
        { 
            get
            { 
                if (IsTransferPending || IsInUpdate) 
                    return true;
 
                return false;
            }
        }
 
        internal PropertyPath Path
        { 
            get { return ParentBinding.Path; } 
        }
 
        internal IValueConverter Converter
        {
            get { return _valueConverter; }
            set { _valueConverter = value; } 
        }
 
        // MultiBinding looks at this to find out what type its MultiValueConverter should 
        // convert back to, when this BindingExpression is not using a user-specified converter.
        internal Type ConverterSourceType 
        {
            get { return _sourceType; }
        }
 
        // the item whose property changes when we UpdateSource
        internal object SourceItem 
        { 
            get { return (Worker != null) ? Worker.SourceItem : null; }
        } 

        // the name of the property that changes when we UpdateSource
        internal string SourcePropertyName
        { 
            get { return (Worker != null) ? Worker.SourcePropertyName : null; }
        } 
 
        // the value of the source property
        internal object SourceValue 
        {
            get { return (Worker != null) ? Worker.RawValue() : DependencyProperty.UnsetValue; }
        }
 
        internal override bool IsParentBindingUpdateTriggerDefault
        { 
            get { return (ParentBinding.UpdateSourceTrigger == UpdateSourceTrigger.Default); } 
        }
 
        internal override bool IsDisconnected
        {
            get { return GetReference(_dataItem) == DisconnectedItem; }
        } 

        //------------------------------------------------------ 
        // 
        //  Internal Methods
        // 
        //-----------------------------------------------------

        // Create a new BindingExpression from the given Bind description
        internal static BindingExpression CreateBindingExpression(DependencyObject d, 
                                                DependencyProperty dp,
                                                Binding binding, 
                                                BindingExpressionBase parent) 
        {
            FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata; 

            if ((fwMetaData != null && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly)
                throw new ArgumentException(SR.Get(SRID.PropertyNotBindable, dp.Name), "dp");
 
            // create the BindingExpression
            BindingExpression bindExpr = new BindingExpression(binding, parent); 
 
            bindExpr.ResolvePropertyDefaultSettings(binding.Mode, binding.UpdateSourceTrigger, fwMetaData);
 
            // Two-way Binding with an empty path makes no sense
            if (bindExpr.IsReflective && binding.XPath == null &&
                    (binding.Path == null || String.IsNullOrEmpty(binding.Path.Path)))
                throw new InvalidOperationException(SR.Get(SRID.TwoWayBindingNeedsPath)); 

            return bindExpr; 
        } 

 
        // Note: For Nullable types, DefaultValueConverter is created for the inner type of the Nullable.
        //       Nullable "Drill-down" service is not provided for user provided Converters.
        internal void SetupDefaultValueConverter(Type type)
        { 
            if (!UseDefaultValueConverter)
                return; 
 
            if (IsInMultiBindingExpression)
            { 
                Converter = null;
                _sourceType = type;
            }
            else if (type != null && type != _sourceType) 
            {
                _sourceType = type; 
 
                Converter = Engine.GetDefaultValueConverter(_sourceType,
                                    TargetProperty.PropertyType, IsReflective); 

                // null converter means failure to create one
                if (Converter == null && TraceData.IsEnabled)
                { 
                     TraceData.Trace(TraceEventType.Error,
                                    TraceData.CannotCreateDefaultValueConverter( 
                                        _sourceType, 
                                        TargetProperty.PropertyType,
                                        (IsReflective ? "two-way" : "one-way")), 
                                    this );
                }

                if (Converter == DefaultValueConverter.ValueConverterNotNeeded) 
                {
                    Converter = null;     // everyone else takes null for an answer. 
                } 
            }
        } 

        // return true if DataContext is set locally (not inherited) on DependencyObject
        internal static bool HasLocalDataContext(DependencyObject d)
        { 
            bool hasModifiers;
            BaseValueSourceInternal valueSource = d.GetValueSource(FrameworkElement.DataContextProperty, null, out hasModifiers); 
            return (valueSource != BaseValueSourceInternal.Inherited) && 
                    (valueSource != BaseValueSourceInternal.Default || hasModifiers);
        } 

        //------------------------------------------------------
        //
        //  Private Properties 
        //
        //----------------------------------------------------- 
 
        private bool CanActivate
        { 
            get { return Status != BindingStatus.Unattached; }
        }

        private BindingWorker Worker { get { return _worker; } } 

        private DynamicValueConverter DynamicConverter 
        { 
            get
            { 
                if (_dynamicConverter == null)
                {
                    Invariant.Assert(Worker != null);
                    // pass along the static source and target types to find same DefaultValueConverter as SetupDefaultValueConverter 
                    _dynamicConverter = new DynamicValueConverter(IsReflective, Worker.SourcePropertyType, Worker.TargetPropertyType);
                } 
                return _dynamicConverter; 
            }
        } 


        //-----------------------------------------------------
        // 
        //  Private Methods
        // 
        //----------------------------------------------------- 

#region Attachment 

        /// 
        /// Attach the binding expression to the given target object and property.
        ///  
        internal override bool AttachOverride(DependencyObject target, DependencyProperty dp)
        { 
            if (!base.AttachOverride(target, dp)) 
                return false;
 
            // listen for InheritanceContext change (if target is mentored)
            if (ParentBinding.SourceReference == null || ParentBinding.SourceReference.UsesMentor)
            {
                DependencyObject mentor = Helper.FindMentor(target); 
                if (mentor != target)
                { 
                    InheritanceContextChangedEventManager.AddListener(target, this); 
                    UsingMentor = true;
 
                    if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach))
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UseMentor( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(mentor))); 
                    } 
                }
            } 

            // listen for lost focus
            if (IsUpdateOnLostFocus)
            { 
                Invariant.Assert(!IsInMultiBindingExpression, "Source BindingExpressions of a MultiBindingExpression should never be UpdateOnLostFocus.");
                LostFocusEventManager.AddListener(target, this); 
            } 

            // attach to things that need tree context.  Do it synchronously 
            // if possible, otherwise post a task.  This gives the parser et al.
            // a chance to assemble the tree before we start walking it.
            AttachToContext(AttachAttempt.First);
            if (Status == BindingStatus.Unattached) 
            {
                if (TraceLog != null) 
                { 
                    string path = (ParentBinding.Path != null) ? ParentBinding.Path.Path : null;
                    TraceLog.Add("Defer attach to {0} of {1}, path = {2}  xpath = {3}", 
                        dp.Name, TraceLog.IdFor(target), path, ParentBinding.XPath);
                }
                Engine.AddTask(this, TaskOps.AttachToContext);
 
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.AttachToContext))
                { 
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.DeferAttachToContext(
                                            TraceData.Identify(this))); 
                }
            }

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831) 
            return true;
        } 
 

        ///  
        /// Detach the binding expression from its target object and property.
        /// 
        internal override void DetachOverride()
        { 
            if (TraceLog != null)
            { 
                TraceLog.Add("Detaching.  status = {0} {1}", Status, new StackTrace()); 
            }
 
            Deactivate();

            DetachFromContext();
 
            // detach from target element
            DependencyObject target = TargetElement; 
            if (target != null && IsUpdateOnLostFocus) 
            {
                LostFocusEventManager.RemoveListener(target, this); 
            }

            ChangeValue(DependencyProperty.UnsetValue, false);
 
            base.DetachOverride();
        } 
 
        // try to get information from the tree context (parent, root, etc.)
        // If everything succeeds, activate the binding. 
        // If anything fails in a way that might succeed after further layout,
        // just return (with status == Unattached).  The binding engine will try
        // again later. For hard failures, set an error status;  no more chances.
        // During the "last chance" attempt, treat all failures as "hard". 
        void AttachToContext(AttachAttempt attempt)
        { 
            // if the target has been GC'd, just give up 
            DependencyObject target = TargetElement;
            if (target == null) 
                return;     // status will be Detached

            if (TraceLog != null)
            { 
                TraceLog.Add("AttachToContext target = {0}, attempt = {1}", TraceLog.IdFor(target), attempt);
            } 
 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.AttachToContext);
            bool traceObjectRef = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.SourceLookup); 

            // certain features should never be tried on the first attempt, as
            // they certainly require at least one layout pass
            if (attempt == AttachAttempt.First) 
            {
                // relative source with ancestor lookup 
                ObjectRef or = ParentBinding.SourceReference; 
                if (or != null && or.TreeContextIsRequired(target))
                { 
                    if (isExtendedTraceEnabled)
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.SourceRequiresTreeContext( 
                                                TraceData.Identify(this),
                                                or.Identify())); 
                    } 

                    return; 
                }
            }

            bool lastChance = (attempt == AttachAttempt.Last); 

            if (isExtendedTraceEnabled) 
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.AttachToContext( 
                                        TraceData.Identify(this),
                                        lastChance ? " (last chance)" : String.Empty));
            }
 
            // if the path has unresolved type names, the parser needs namesapce
            // information to resolve them.  See XmlTypeMapper.GetTypeFromName. 
            // Ignore this requirement during the last chance, and just let 
            // GetTypeFromName fail if it wants to.
            if (!lastChance && ParentBinding.TreeContextIsRequired) 
            {
                if (target.GetValue(XmlAttributeProperties.XmlnsDictionaryProperty) == null ||
                    target.GetValue(XmlAttributeProperties.XmlNamespaceMapsProperty) == null)
                { 
                    if (isExtendedTraceEnabled)
                    { 
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.PathRequiresTreeContext(
                                                TraceData.Identify(this), 
                                                ParentBinding.Path.Path));
                    }

                    return; 
                }
            } 
 
            // if the binding uses a mentor, check that it exists
            DependencyObject mentor = !UsingMentor ? target :  Helper.FindMentor(target); 
            if (mentor == null)
            {
                if (isExtendedTraceEnabled)
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.NoMentorExtended( 
                                            TraceData.Identify(this))); 
                }
 
                if (lastChance)
                {
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoMentor, this); 
                    } 
                }
                return; 
            }

            // determine the element whose DataContext governs this BindingExpression
            DependencyObject contextElement = null;     // no context element 
            bool contextElementFound = true;
            if (ParentBinding.SourceReference == null) 
            { 
                contextElement = mentor;    // usually the mentor/target element
 
                // special cases:
                // 1. if target property is DataContext, use the target's parent.
                //      This enables  and
                // 2. if the target is ContentPresenter and the target property 
                //      is Content, use the parent.  This enables
                //           
                // 3. if target is CVS, and its inheritance context was set 
                //      via DataContext, use the mentor's parent.  This enables
                //        
                CollectionViewSource cvs;
                if (TargetProperty == FrameworkElement.DataContextProperty ||
                    (TargetProperty == ContentPresenter.ContentProperty &&
                            target is ContentPresenter) || 
                    (UsingMentor &&
                            (cvs = target as CollectionViewSource) != null && 
                            cvs.PropertyForInheritanceContext == FrameworkElement.DataContextProperty) 
                    )
                { 
                    contextElement = FrameworkElement.GetFrameworkParent(contextElement);
                    contextElementFound = (contextElement != null);
                }
            } 
            else
            { 
                RelativeObjectRef ror = ParentBinding.SourceReference as RelativeObjectRef; 
                if (ror != null && ror.ReturnsDataContext)
                { 
                    object o = ror.GetObject(mentor, new ObjectRefArgs() { IsTracing = traceObjectRef});
                    contextElement = o as DependencyObject;    // ref to another element's DataContext
                    contextElementFound = (o != DependencyProperty.UnsetValue);
                } 
            }
 
            if (isExtendedTraceEnabled) 
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.ContextElement(
                                        TraceData.Identify(this),
                                        TraceData.Identify(contextElement),
                                        contextElementFound ? "OK" : "error")); 
            }
 
            // if we need a context element, check that we found it 
            if (!contextElementFound)
            { 
                if (lastChance)
                {
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoDataContext, this); 
                    } 
                }
 
                return;
            }

            // determine the source object, from which the path evaluation starts 
            object source;
            ObjectRef sourceRef; 
 
            if (contextElement != null)
            { 
                source = contextElement.GetValue(FrameworkElement.DataContextProperty);

                // if the data context is default null, try again later;  future
                // layout may change the inherited value. 
                // Ignore this requirement during the last chance, and just let
                // the binding to null DataContext proceed. 
                if (source == null && !lastChance && !HasLocalDataContext(contextElement)) 
                {
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.NullDataContext(
                                                TraceData.Identify(this))); 
                    }
 
                    return; 
                }
            } 
            else if ((sourceRef = ParentBinding.SourceReference) != null)
            {
                ObjectRefArgs args = new ObjectRefArgs() {
                                        IsTracing = traceObjectRef, 
                                        ResolveNamesInTemplate = ResolveNamesInTemplate,
                                        }; 
                source = sourceRef.GetDataObject(mentor, args); 

                // check that the source could be found 
                if (source == DependencyProperty.UnsetValue)
                {
                    if (lastChance)
                    { 
                        SetStatus(BindingStatus.PathError);
                        if (TraceData.IsEnabled) 
                        { 
                            TraceData.Trace(TraceLevel, TraceData.NoSource(sourceRef), this);
                        } 
                    }

                    return;
                } 
                else if (!lastChance && args.NameResolvedInOuterScope)
                { 
                    // if ElementName resolved in an outer scope, it's possible 
                    // that future work might add the name to an inner scope.
                    // Schedule a task to check this. 
                    Engine.AddTask(this, TaskOps.VerifySourceReference);
                }
            }
            else 
            {
                // we get here only if we need ambient data context, but there 
                // is no context element.  E.g. binding the DataContext property 
                // of an element with no parent.  Just use null.
                source = null; 
            }

            // if we get this far, all the ingredients for a successful binding
            // are present.  Remember what we've found and activate the binding. 
            if (contextElement != null)
                _ctxElement = new WeakReference(contextElement); 
 
            // attach to context element
            ChangeWorkerSources(null, 0); 

            if (!UseDefaultValueConverter)
            {
                _valueConverter = ParentBinding.Converter; 

                if (_valueConverter == null) 
                { 
                    throw new InvalidOperationException(SR.Get(SRID.MissingValueConverter)); // report instead of throw?
                } 
            }

            // join the right binding group (if any)
            JoinBindingGroup(IsReflective, contextElement); 

            SetStatus(BindingStatus.Inactive); 
 
            // inner BindingExpressions of PriorityBindingExpressions may not need to be activated
            if (IsInPriorityBindingExpression) 
                ParentPriorityBindingExpression.InvalidateChild(this);
            else    // singular BindingExpressions and those in MultiBindingExpressions should always activate
                Activate(source);
 
            GC.KeepAlive(target);   // keep target alive during activation (bug 956831)
        } 
 
        // Detach from things that may require tree context
        private void DetachFromContext() 
        {
            // detach from data source
            if (_dataProvider != null)
            { 
                if (TraceLog != null)
                { 
                    TraceLog.Add("-OnDataChanged to {0}", TraceLog.IdFor(_dataProvider)); 
                }
                DataChangedEventManager.RemoveListener(_dataProvider, this); 
            }

            if (!UseDefaultValueConverter)
            { 
                _valueConverter = null;
            } 
 
            if (!IsInBindingExpressionCollection)
                ChangeSources(null); 

            if (UsingMentor)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                    InheritanceContextChangedEventManager.RemoveListener(target, this); 
            } 

            _ctxElement = null; 
        }

#endregion Attachment
 
#region Activation
 
        // Activate the BindingExpression, if necessary and possible 
        internal override void Activate()
        { 
            if (!CanActivate)
                return;

            if (_ctxElement == null) 
            {
                // only activate once if there's an explicit source 
                if (Status == BindingStatus.Inactive) 
                {
                    DependencyObject target = TargetElement; 
                    if (target != null)
                    {
                        if (UsingMentor)
                        { 
                            target = Helper.FindMentor(target);
                            if (target == null) 
                            { 
                                // mentor is not available
                                SetStatus(BindingStatus.PathError); 
                                if (TraceData.IsEnabled)
                                {
                                    TraceData.Trace(TraceEventType.Error, TraceData.NoMentor, this);
                                } 
                                return;
                            } 
                        } 
                        Activate(ParentBinding.SourceReference.GetDataObject(target,
                                                                new ObjectRefArgs() { ResolveNamesInTemplate = ResolveNamesInTemplate })); 
                    }
                }
            }
            else 
            {
                DependencyObject contextElement = ContextElement; 
                if (contextElement == null) 
                {
                    // context element has been GC'd, or unavailable (e.g. no mentor) 
                    SetStatus(BindingStatus.PathError);
                    if (TraceData.IsEnabled)
                    {
                        TraceData.Trace(TraceEventType.Error, TraceData.NoDataContext, this); 
                    }
                    return; 
                } 

                object item = contextElement.GetValue(FrameworkElement.DataContextProperty); 

                // if binding inactive or the data item has changed, (re-)activate
                if (Status == BindingStatus.Inactive || !Object.Equals(item, DataItem))
                { 
                    Activate(item);
                } 
            } 
        }
 
        internal void Activate(object item)
        {
            DependencyObject target = TargetElement;
            if (target == null) 
                return;
 
            if (item == DisconnectedItem) 
            {
                // disconnect from the former item, with the least acceptable impact 
                Disconnect();
                return;
            }
 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate);
 
            Deactivate(); 

            if (TraceLog != null) 
                TraceLog.Add("Activate item = {0}", TraceLog.IdFor(item));

            // apply magic (for CVS, DSP, etc.), unless asked not to
            if (!ParentBinding.BindsDirectlyToSource) 
            {
                CollectionViewSource cvs = item as CollectionViewSource; 
                this.CollectionViewSource = cvs; 
                if (cvs != null)
                { 
                    item = cvs.CollectionView;

                    // the CVS is one of our implicit sources
                    ChangeWorkerSources(null, 0); 

                    if (isExtendedTraceEnabled) 
                    { 
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UseCVS( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(cvs)));
                    }
                } 
                else
                { 
                    // when the source is DataSourceProvider, use its data instead 
                    item = DereferenceDataProvider(item);
                } 
            }

            _dataItem = CreateReference(item);
 
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.ActivateItem(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(item)));
            }

            if (Worker == null) 
                CreateWorker();
 
            // mark the BindingExpression active 
            SetStatus(BindingStatus.Active);
 
            // attach to data item (may set error status)
            Worker.AttachDataItem();

            // 

 
            // initial transfer 
            bool initialTransferIsUpdate = IsOneWayToSource;
            object currentValue; 
            if (ShouldUpdateWithCurrentValue(target, out currentValue))
            {
                initialTransferIsUpdate = true;
                ChangeValue(currentValue, /*notify*/false); 
                NeedsUpdate = true;
            } 
 
            if (!initialTransferIsUpdate)
            { 
                ValidationError error;
                object value = GetInitialValue(target, out error);
                if (value != NullDataItem)
                { 
                    TransferValue(value, false);
                } 
 
                if (error != null)
                { 
                    UpdateValidationError(error);
                }
            }
            else if (!IsInMultiBindingExpression)   // MultiBinding initiates its own update 
            {
                UpdateValue(); 
            } 

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831) 
        }

        // return the value for the initial data transfer.  Specifically:
        //      normal case - return UnsetValue (we'll get the value from the source object) 
        //      valid proposed value - return the proposed value
        //      invalid proposed value - two subcases: 
        //          one-way binding - return default/fallback value 
        //          two-way binding - retrun NullDataItem (meaning "don't transfer")
        // 
        //      In both subcases, adopt the validation errors discovered earlier.
        //      In the two-way subcase, instead of a source-to-target transfer, we set the
        //      the target property to the (saved) raw proposed value, as if the user
        //      had edited this property. 
        object GetInitialValue(DependencyObject target, out ValidationError error)
        { 
            object proposedValue; 

            // find the binding group this binding would join if it were two-way (even if it isn't) 
            BindingGroup bindingGroup = RootBindingExpression.FindBindingGroup(true, ContextElement);
            BindingGroup.ProposedValueEntry entry;

            // get the proposed value from the binding group 
            if (bindingGroup == null ||
                (entry = bindingGroup.GetProposedValueEntry(SourceItem, SourcePropertyName)) == null) 
            { 
                // no proposed value
                error = null; 
                proposedValue = DependencyProperty.UnsetValue;
            }
            else
            { 
                // adopt the validation error (possibly null)
                error = entry.ValidationError; 
 
                if (IsReflective && TargetProperty.IsValidValue(entry.RawValue))
                { 
                    // two-way binding - set the target property directly
                    target.SetValue(TargetProperty, entry.RawValue);
                    proposedValue = NullDataItem;
                    bindingGroup.RemoveProposedValueEntry(entry); 
                }
                else if (entry.ConvertedValue == DependencyProperty.UnsetValue) 
                { 
                    // invalid proposed value - use fallback/default
                    proposedValue = UseFallbackValue(); 
                }
                else
                {
                    // valid proposed value 
                    proposedValue = entry.ConvertedValue;
                } 
 
                // if this binding didn't take over responsibility for the proposed
                // value, add it to the list of bindings using the proposed value 
                if (proposedValue != NullDataItem)
                {
                    bindingGroup.AddBindingForProposedValue(this, SourceItem, SourcePropertyName);
                } 
            }
 
            return proposedValue; 
        }
 
        internal override void Deactivate()
        {
            if (TraceLog != null)
                TraceLog.Add("Deactivate"); 

            // inactive BindingExpressions don't need any more work 
            if (Status == BindingStatus.Inactive) 
                return;
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate))
            {
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.Deactivate( 
                                        TraceData.Identify(this)));
            } 
 
            // stop transfers
            CancelPendingTasks(); 

            // detach from data item
            if (Worker != null)
                Worker.DetachDataItem(); 

            // restore default value, in case source/converter fail to provide a good value 
            ChangeValue(DefaultValueObject, false); 

            // don't keep a handle to old data item if the BindingExpression is inactive 
            _dataItem = null;

            SetStatus(BindingStatus.Inactive);
        } 

        // disconnect from the former item, with the least acceptable impact. 
        // This arises when a container is removed from an ItemsControl. 
        internal override void Disconnect()
        { 
            // disconnect this binding from its former item
            _dataItem = CreateReference(DisconnectedItem);

            if (Worker == null) 
                return;
 
            Worker.AttachDataItem(); 

            base.Disconnect(); 
        }

        // if the root item is a DataSourceProvider, use its Data instead
        // and listen for DataChanged events.  (Unless overridden explicitly 
        // by the BindsDirectlyToSource property).
        private object DereferenceDataProvider(object item) 
        { 
            DataSourceProvider dataProvider = item as DataSourceProvider;
            if (dataProvider != _dataProvider) 
            {
                // we have a new data provider - retarget the event handler
                if (_dataProvider != null)
                { 
                    if (TraceLog != null)
                    { 
                        TraceLog.Add("-OnDataChanged to {0}", TraceLog.IdFor(_dataProvider)); 
                    }
                    DataChangedEventManager.RemoveListener(_dataProvider, this); 
                }

                _dataProvider = dataProvider;
 
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Activate))
                { 
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.UseDataProvider(
                                            TraceData.Identify(this), 
                                            TraceData.Identify(_dataProvider)));
                }

                if (_dataProvider != null) 
                {
                    if (TraceLog != null) 
                    { 
                        TraceLog.Add("+OnDataChanged to {0}", TraceLog.IdFor(_dataProvider));
                    } 
                    DataChangedEventManager.AddListener(_dataProvider, this);
                    _dataProvider.InitialLoad();
                }
            } 

            return (_dataProvider != null) ? _dataProvider.Data : item; 
        } 

#endregion Activation 

#region Worker

        private void CreateWorker() 
        {
            Invariant.Assert(Worker == null, "duplicate call to CreateWorker"); 
 
            _worker = new ClrBindingWorker(this, Engine);
        } 

        // worker calls here if it changes its dependency sources
        // n is the number of real entries in newWorkerSources (which may be longer)
        internal void ChangeWorkerSources(WeakDependencySource[] newWorkerSources, int n) 
        {
            int offset = 0; 
            int size = n; 

            // create the new sources array, and add the context and CollectionViewSource elements 
            DependencyObject contextElement = ContextElement;
            CollectionViewSource cvs = CollectionViewSource;
            bool usesLanguage = UsesLanguage;
 
            if (contextElement != null)
                ++size; 
            if (cvs != null) 
                ++size;
            if (usesLanguage) 
                ++size;

            WeakDependencySource[] newSources = (size > 0) ? new WeakDependencySource[size] : null;
 
            if (contextElement != null)
            { 
                newSources[offset++] = new WeakDependencySource(_ctxElement, FrameworkElement.DataContextProperty); 
            }
 
            if (cvs != null)
            {
                WeakReference wr = _collectionViewSource as WeakReference;
                newSources[offset++] = 
                    (wr != null) ? new WeakDependencySource(wr, CollectionViewSource.ViewProperty)
                                 : new WeakDependencySource(cvs, CollectionViewSource.ViewProperty); 
            } 

            if (usesLanguage) 
            {
                newSources[offset++] = new WeakDependencySource(TargetElementReference, FrameworkElement.LanguageProperty);
            }
 
            // add the worker's sources
            if (n > 0) 
                Array.Copy(newWorkerSources, 0, newSources, offset, n); 

            // tell the property engine 
            ChangeSources(newSources);
        }

#endregion Worker 

#region Value 
 
        // transfer a value from the source to the target
        void TransferValue() 
        {
            TransferValue(DependencyProperty.UnsetValue, false);
        }
 
        // transfer a value from the source to the target
        internal void TransferValue(object newValue, bool isASubPropertyChange) 
        { 
            // if the target element has been GC'd, do nothing
            DependencyObject target = TargetElement; 
            if (target == null)
                return;

            // if the BindingExpression hasn't activated, do nothing 
            if (Worker == null)
                return; 
 
            Type targetType = GetEffectiveTargetType();
            IValueConverter implicitConverter = null; 
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Transfer);

            // clear the Pending flag before actually doing the transfer.  That way if another
            // thread sets the flag, we'll schedule another transfer.  This might do more 
            // transfers than absolutely necessary, but it guarantees that we'll eventually pick
            // up the value from the last change. 
            IsTransferPending = false; 
            IsInTransfer = true;
 
            UsingFallbackValue = false;

            // get the raw value from the source
            object value = (newValue == DependencyProperty.UnsetValue) ? Worker.RawValue() : newValue; 

            if (isExtendedTraceEnabled) 
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.GetRawValue( 
                                        TraceData.Identify(this),
                                        TraceData.Identify(value)));
            }
 
            // apply any necessary conversions
            if (value != DependencyProperty.UnsetValue) 
            { 
            #if !TargetNullValueBC  //BreakingChange
                bool doNotSetStatus = false; 
            #endif

                if (!UseDefaultValueConverter)
                { 
                    // if there's a user-defined converter, call it without catching
                    // exceptions (bug 992237).  It can return DependencyProperty.UnsetValue 
                    // to indicate a failure to convert. 
                    value = Converter.Convert(value, targetType, ParentBinding.ConverterParameter, GetCulture());
 
                    if (isExtendedTraceEnabled)
                    {
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.UserConverter( 
                                                TraceData.Identify(this),
                                                TraceData.Identify(value))); 
                    } 

                    // chain in a default value converter if the returned value's type is not compatible with the targetType 
                    if (   ((value != null) && (value != Binding.DoNothing) && (value != DependencyProperty.UnsetValue))
                        && !targetType.IsAssignableFrom(value.GetType()))
                    {
                        // the dynamic converter is shared between Transfer and Update directions 
                        // once instantiated, DefaultValueConverters are kept in a lookup table, making swapping
                        // default value converters in the DynamicValueConverter reasonably fast 
                        implicitConverter = DynamicConverter; 
                    }
                } 
                else
                {
                    // if there's no user-defined converter, use the default converter (if any)
                    // we chose earlier (in SetupDefaultValueConverter) 
                    implicitConverter = Converter;
                } 
 
                // apply an implicit conversion, if needed.  This can be
                //  a) null conversion 
                //  b) string formatting
                //  c) type conversion
                if ((value != Binding.DoNothing) && (value != DependencyProperty.UnsetValue))
                { 
                    // ultimately, TargetNullValue should get assigned implicitly,
                    // even if the user doesn't declare it.  We can't do this yet because 
                    // of back-compat.  I wrote it both ways, and #if'd out the breaking 
                    // change.
                #if TargetNullValueBC   //BreakingChange 
                    if (IsNullValue(value))
                #else
                    if (EffectiveTargetNullValue != DependencyProperty.UnsetValue &&
                        IsNullValue(value)) 
                #endif
                    { 
                        value = EffectiveTargetNullValue; 

                        if (isExtendedTraceEnabled) 
                        {
                            TraceData.Trace(TraceEventType.Warning,
                                                TraceData.NullConverter(
                                                    TraceData.Identify(this), 
                                                    TraceData.Identify(value)));
                        } 
                    } 
                #if !TargetNullValueBC   //BreakingChange
                    // For DBNull, unless there's a user converter, we handle it here 
                    else if ((value == DBNull.Value) && (Converter == null || UseDefaultValueConverter))
                    {
                        if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
                        { 
                            value = null;
                        } 
                        else 
                        {
                            value = DependencyProperty.UnsetValue; 
                            // The 3.5 code failed to set the status to UpdateTargetError in this
                            // case.  It's a bug, but we have to maintain the buggy behavior for
                            // back-compat.
                            doNotSetStatus = true; 
                        }
 
                        if (isExtendedTraceEnabled) 
                        {
                            TraceData.Trace(TraceEventType.Warning, 
                                                TraceData.ConvertDBNull(
                                                    TraceData.Identify(this),
                                                    TraceData.Identify(value)));
                        } 

                    } 
                #endif 
                    else if (implicitConverter != null || EffectiveStringFormat != null)
                    { 
                        // call a DefaultValueConverter:
                        // NOTE:
                        // here we pass in the TargetElement that is expected by our default value converters;
                        // this does violate the general rule that value converters should be stateless 
                        // and must not be aware of e.g. their target element.
                        // Our DefaultValueConverters are all internal and only use this target element 
                        // to determine a BaseUri for their TypeConverters 
                        // -> hence a reluctant exeption of above rule
                        value = ConvertHelper(implicitConverter, value, targetType, TargetElement, GetCulture()); 

                        if (isExtendedTraceEnabled)
                        {
                            TraceData.Trace(TraceEventType.Warning, 
                                                TraceData.DefaultConverter(
                                                    TraceData.Identify(this), 
                                                    TraceData.Identify(value))); 
                        }
                    } 
                }

                if (
            #if !TargetNullValueBC   //BreakingChange 
                    !doNotSetStatus &&
            #endif 
                    value == DependencyProperty.UnsetValue) 
                {
                    SetStatus(BindingStatus.UpdateTargetError); 
                }
            }

            // the special value DoNothing means no error, but no data transfer 
            if (value == Binding.DoNothing)
                goto Done; 
 
            // if the value isn't acceptable to the target property, don't use it
            // (in MultiBinding, the value will go through the multi-converter, so 
            // it's too early to make this judgment)
            if (!IsInMultiBindingExpression && value != IgnoreDefaultValue &&
                value != DependencyProperty.UnsetValue && !TargetProperty.IsValidValue(value))
            { 
                if (TraceData.IsEnabled && !IsInBindingExpressionCollection)
                { 
                    TraceData.Trace(TraceLevel, TraceData.BadValueAtTransfer, value, this); 
                }
 
                if (isExtendedTraceEnabled)
                {
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.BadValueAtTransferExtended( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(value))); 
                } 

                value = DependencyProperty.UnsetValue; 

                if (Status == BindingStatus.Active)
                    SetStatus(BindingStatus.UpdateTargetError);
            } 

            // If we haven't obtained a value yet, 
            // use the fallback value.  This could happen when the currency 
            // has moved off the end of the collection, e.g.
            if (value == DependencyProperty.UnsetValue) 
            {
                value = UseFallbackValue();

                if (isExtendedTraceEnabled) 
                {
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.UseFallback( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(value))); 
                }
            }

            // Ignore a default source value by setting the value to NoValue; 
            // this causes the property engine to obtain the value elsewhere
            if (value == IgnoreDefaultValue) 
            { 
                value = Expression.NoValue;
            } 

            if (isExtendedTraceEnabled)
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.TransferValue(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(value))); 
            }
 
            // if this is a re-transfer after a source update and the value
            // hasn't changed, don't do any more work.
            if (IsInUpdate && Object.Equals(value, Value))
            { 
                goto Done;
            } 
 
            // update the cached value
            ChangeValue(value, true); 
            Invalidate(isASubPropertyChange);
            OnTargetUpdated();
            ValidateOnTargetUpdated();
 
        Done:
            IsInTransfer = false; 
 
            GC.KeepAlive(target);   // keep target alive during transfer (bug 956831)
        } 

        // run the validation rules marked as ValidateOnTargetUpdated
        private void ValidateOnTargetUpdated()
        { 
            // update the validation state
            ValidationError validationError = null; 
 
            Collection validationRules = ParentBinding.ValidationRulesInternal;
            CultureInfo culture = null; 

            bool needDataErrorRule = ParentBinding.ValidatesOnDataErrors;

            if (validationRules != null) 
            {
                // these may be needed by several rules, but only compute them once 
                object rawValue = DependencyProperty.UnsetValue; 
                object itemValue = DependencyProperty.UnsetValue;
 
                foreach (ValidationRule validationRule in validationRules)
                {
                    if (validationRule.ValidatesOnTargetUpdated)
                    { 
                        if (validationRule is DataErrorValidationRule)
                        { 
                            needDataErrorRule = false; 
                        }
 
                        object value;

                        switch (validationRule.ValidationStep)
                        { 
                            case ValidationStep.RawProposedValue:
                                if (rawValue == DependencyProperty.UnsetValue) 
                                { 
                                    rawValue = GetRawProposedValue();
                                } 
                                value = rawValue;
                                break;
                            case ValidationStep.ConvertedProposedValue:
                                if (itemValue == DependencyProperty.UnsetValue) 
                                {
                                    itemValue = Worker.RawValue(); 
                                } 
                                value = itemValue;
                                break; 
                            case ValidationStep.UpdatedValue:
                            case ValidationStep.CommittedValue:
                                value = this;
                                break; 
                            default:
                                throw new InvalidOperationException(SR.Get(SRID.ValidationRule_UnknownStep, validationRule.ValidationStep, validationRule)); 
                        } 

                        // lazy-fetch culture (avoids exception when target DP is Language) 
                        if (culture == null)
                        {
                            culture = GetCulture();
                        } 

                        validationError = RunValidationRule(validationRule, value, culture); 
                        if (validationError != null) 
                            break;
                    } 
                }
            }

            if (needDataErrorRule && validationError == null) 
            {
                // lazy-fetch culture (avoids exception when target DP is Language) 
                if (culture == null) 
                {
                    culture = GetCulture(); 
                }

                validationError = RunValidationRule(DataErrorValidationRule.Instance, this, culture);
            } 

            UpdateValidationError(validationError); 
        } 

        ValidationError RunValidationRule(ValidationRule validationRule, object value, CultureInfo culture) 
        {
            ValidationError error;

            ValidationResult validationResult = validationRule.Validate(value, culture); 

            if (validationResult.IsValid) 
            { 
                error = null;
            } 
            else
            {
                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update))
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.ValidationRuleFailed( 
                                            TraceData.Identify(this), 
                                            TraceData.Identify(validationRule)));
                } 

                error = new ValidationError(validationRule, this, validationResult.ErrorContent, null);
            }
 
            return error;
        } 
 
        private object ConvertHelper(IValueConverter converter, object value, Type targetType, object parameter, CultureInfo culture)
        { 
            // use the StringFormat (if appropriate) in preference to the default converter
            string stringFormat = EffectiveStringFormat;
            Invariant.Assert(converter != null || stringFormat != null);
 
            // PreSharp uses message numbers that the C# compiler doesn't know about.
            // Disable the C# complaints, per the PreSharp documentation. 
            #pragma warning disable 1634, 1691 

            // PreSharp complains about catching NullReference (and other) exceptions. 
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly.
            #pragma warning disable 56500

            object convertedValue = null; 
            try
            { 
                if (stringFormat != null) 
                {
                    convertedValue = String.Format(culture, stringFormat, value); 
                }
                else
                {
                    convertedValue = converter.Convert(value, targetType, parameter, culture); 
                }
            } 
 
            // Catch all exceptions.  There is no app code on the stack,
            // so the exception isn't actionable by the app. 
            // Yet we don't want to crash the app.
            catch (Exception ex)
            {
                // the DefaultValueConverter can end up calling BaseUriHelper.GetBaseUri() 
                // which can raise SecurityException if the app does not have the right FileIO privileges
                if (CriticalExceptions.IsCriticalApplicationException(ex)) 
                    throw; 

                if (TraceData.IsEnabled) 
                {
                    string name = String.IsNullOrEmpty(stringFormat) ? converter.GetType().Name : "StringFormat";
                    TraceData.Trace(TraceLevel,
                            TraceData.BadConverterForTransfer( 
                                name,
                                AvTrace.ToStringHelper(value), 
                                AvTrace.TypeName(value)), 
                            this, ex);
                } 
                convertedValue = DependencyProperty.UnsetValue;
            }
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled)
                { 
                    TraceData.Trace(TraceLevel, 
                            TraceData.BadConverterForTransfer(
                                converter.GetType().Name, 
                                AvTrace.ToStringHelper(value),
                                AvTrace.TypeName(value)),
                            this);
                } 
                convertedValue = DependencyProperty.UnsetValue;
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            return convertedValue;
        }
 
        private object ConvertBackHelper(IValueConverter converter,
                                         object value, 
                                         Type sourceType, 
                                         object parameter,
                                         CultureInfo culture) 
        {
            Invariant.Assert(converter != null);

            // PreSharp uses message numbers that the C# compiler doesn't know about. 
            // Disable the C# complaints, per the PreSharp documentation.
            #pragma warning disable 1634, 1691 
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly. 
            #pragma warning disable 56500

            object convertedValue = null;
            try 
            {
                convertedValue = converter.ConvertBack(value, sourceType, parameter, culture); 
            } 

            // Catch all exceptions.  There is no app code on the stack, 
            // so the exception isn't actionable by the app.
            // Yet we don't want to crash the app.
            catch (Exception ex)
            { 
                // the DefaultValueConverter can end up calling BaseUriHelper.GetBaseUri()
                // which can raise SecurityException if the app does not have the right FileIO privileges 
                ex = CriticalExceptions.Unwrap(ex); 
                if (CriticalExceptions.IsCriticalApplicationException(ex))
                    throw; 

                if (TraceData.IsEnabled)
                {
                    TraceData.Trace(TraceEventType.Error, 
                        TraceData.BadConverterForUpdate(
                            AvTrace.ToStringHelper(Value), 
                            AvTrace.TypeName(value)), 
                        this, ex);
                } 

                ProcessException(ex, ValidatesOnExceptions);
                convertedValue = DependencyProperty.UnsetValue;
            } 
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error, 
                        TraceData.BadConverterForUpdate(
                            AvTrace.ToStringHelper(Value),
                            AvTrace.TypeName(value)),
                        this); 
                }
                convertedValue = DependencyProperty.UnsetValue; 
            } 

            #pragma warning restore 56500 
            #pragma warning restore 1634, 1691

            return convertedValue;
        } 

        internal void ScheduleTransfer(bool isASubPropertyChange) 
        { 
            if (isASubPropertyChange && Converter != null)
            { 
                // a converter doesn't care about sub-property changes
                isASubPropertyChange = false;
            }
 
            TransferValue(DependencyProperty.UnsetValue, isASubPropertyChange);
        } 
 

        void OnTargetUpdated() 
        {
            if (NotifyOnTargetUpdated)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                { 
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression 
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression)    // in ProrityBinding, and either active 
                            ||  (IsAttaching && (Status==BindingStatus.Active || UsingFallbackValue) // or about to become active
                            )
                        )
                    { 
                        // while attaching a normal (not style-defined) BindingExpression,
                        // we must defer raising the event until after the 
                        // property has been invalidated, so that the event handler 
                        // gets the right value if it asks (bug 1036862)
                        if (IsAttaching && RootBindingExpression == target.ReadLocalValue(TargetProperty)) 
                        {
                            Engine.AddTask(this, TaskOps.RaiseTargetUpdatedEvent);
                        }
                        else 
                        {
                            OnTargetUpdated(target, TargetProperty); 
                        } 
                    }
                } 
            }
        }

        void OnSourceUpdated() 
        {
            if (NotifyOnSourceUpdated) 
            { 
                DependencyObject target = TargetElement;
                if (target != null) 
                {
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression))   // not an inactive BindingExpression 
                    {
                        OnSourceUpdated(target, TargetProperty); 
                    } 
                }
            } 
        }


        // transfer a value from target to source 
        internal override void Update(bool synchronous)
        { 
            // various reasons not to update: 
            if (   !NeedsUpdate                     // nothing to do
                || !IsReflective                    // no update desired 
                || IsInTransfer                     // in a transfer
                || Worker == null                   // not activated
                || !Worker.CanUpdate                // no source (currency moved off end)
                ) 
                return;
 
            if (synchronous) 
            {
                UpdateValue(); 
            }
            else
            {
                Engine.AddTask(this, TaskOps.UpdateValue); 
            }
        } 
 
        internal override object ConvertProposedValue(object value)
        { 
            object rawValue = value;
            bool isExtendedTraceEnabled = TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update);
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.UpdateRawValue( 
                                        TraceData.Identify(this), 
                                        TraceData.Identify(value)));
            } 

            Type sourceType = Worker.SourcePropertyType;
            IValueConverter implicitConverter = null;
            CultureInfo culture = GetCulture(); 

            // apply user-defined converter 
            if (Converter != null) 
            {
                if (!UseDefaultValueConverter) 
                {
                    // if there's a user-defined converter, call it without catching
                    // exceptions (bug 992237).  It can return DependencyProperty.UnsetValue
                    // to indicate a failure to convert. 
                    value = Converter.ConvertBack(value, sourceType, ParentBinding.ConverterParameter, culture);
 
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.UserConvertBack(
                                                TraceData.Identify(this),
                                                TraceData.Identify(value)));
                    } 

                    // chain in a default value converter if the returned value's type is not compatible with the sourceType 
                    if (value != Binding.DoNothing && value != DependencyProperty.UnsetValue && 
                        !IsValidValueForUpdate(value, sourceType))
                    { 
                        // the dynamic converter is shared between Transfer and Update directions
                        // once instantiated, DefaultValueConverters are kept in a lookup table, making swapping
                        // default value converters reasonably fast
                        implicitConverter = DynamicConverter; 
                    }
                } 
                else 
                {
                    implicitConverter = Converter; 
                }
            }

            // apply an implicit conversion, if needed.  This can be 
            //  a) null conversion
            //  b) type conversion 
            if (value != Binding.DoNothing && value != DependencyProperty.UnsetValue) 
            {
                if (IsNullValue(value)) 
                {
                    if (Worker.IsDBNullValidForUpdate)
                    {
                        value = DBNull.Value; 
                    }
                    else 
                    { 
                        value = NullValueForType(sourceType);
                    } 
                }
                else if (implicitConverter != null)
                {
                    // here we pass in the TargetElement, see NOTE of caution in TransferValue() why this is ok 
                    value = ConvertBackHelper(implicitConverter, value, sourceType, this.TargetElement, culture);
 
                    if (isExtendedTraceEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Warning, 
                                            TraceData.DefaultConvertBack(
                                                TraceData.Identify(this),
                                                TraceData.Identify(value)));
                    } 
                }
            } 
 
            if (isExtendedTraceEnabled)
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.Update(
                                        TraceData.Identify(this),
                                        TraceData.Identify(value))); 
            }
 
            // if the conversion failed, signal a validation error 
            if (value == DependencyProperty.UnsetValue)
            { 
                if (ValidationError == null)
                {
                    ValidationError validationError = new ValidationError(ConversionValidationRule.Instance, this, SR.Get(SRID.Validation_ConversionFailed, rawValue), null);
                    UpdateValidationError(validationError); 
                }
            } 
 
            return value;
        } 

        /// 
        /// Get the converted proposed value and inform the binding group
        ///  
        internal override bool ObtainConvertedProposedValue(BindingGroup bindingGroup)
        { 
            bool result = true; 
            object value;
 
            if (NeedsUpdate)
            {
                value = bindingGroup.GetValue(this);
                if (value != DependencyProperty.UnsetValue) 
                {
                    value = ConvertProposedValue(value); 
                    if (value == DependencyProperty.UnsetValue) 
                    {
                        result = false; 
                    }
                }
            }
            else 
            {
                value = BindingGroup.DeferredSourceValue; 
            } 

            bindingGroup.SetValue(this, value); 
            return result;
        }

        internal override object UpdateSource(object value) 
        {
            // If there is a failure to convert, then Update failed. 
            if (value == DependencyProperty.UnsetValue) 
            {
                SetStatus(BindingStatus.UpdateSourceError); 
            }

            if (value == Binding.DoNothing || value == DependencyProperty.UnsetValue ||
                ShouldIgnoreUpdate()) 
            {
                return value; 
            } 

 
            // PreSharp uses message numbers that the C# compiler doesn't know about.
            // Disable the C# complaints, per the PreSharp documentation.
            #pragma warning disable 1634, 1691
 
            // PreSharp complains about catching NullReference (and other) exceptions.
            // It doesn't recognize that IsCritical[Application]Exception() handles these correctly. 
            #pragma warning disable 56500 

            try 
            {
                BeginSourceUpdate();
                Worker.UpdateValue(value);
            } 

            // Catch all exceptions.  There is no app code on the stack, 
            // so the exception isn't actionable by the app. 
            // Yet we don't want to crash the app.
            catch (Exception ex) 
            {
                ex = CriticalExceptions.Unwrap(ex);
                if (CriticalExceptions.IsCriticalApplicationException(ex))
                    throw; 

                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this, ex); 

                ProcessException(ex, (ValidatesOnExceptions || BindingGroup != null)); 
                SetStatus(BindingStatus.UpdateSourceError);
                value = DependencyProperty.UnsetValue;
            }
            catch // non CLS compliant exception 
            {
                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this); 

                SetStatus(BindingStatus.UpdateSourceError); 
                value = DependencyProperty.UnsetValue;
            }
            finally
            { 
                EndSourceUpdate();
            } 
 
            #pragma warning restore 56500
            #pragma warning restore 1634, 1691 

            OnSourceUpdated();

            return value; 
        }
 
        ///  
        /// Update the source value and inform the binding group
        ///  
        internal override bool UpdateSource(BindingGroup bindingGroup)
        {
            bool result = true;
            if (NeedsUpdate) 
            {
                object value = bindingGroup.GetValue(this); 
                value = UpdateSource(value); 
                bindingGroup.SetValue(this, value);
                if (value == DependencyProperty.UnsetValue) 
                {
                    result = false;
                }
            } 
            return result;
        } 
 
        /// 
        /// Store the value in the binding group 
        /// 
        internal override void StoreValueInBindingGroup(object value, BindingGroup bindingGroup)
        {
            bindingGroup.SetValue(this, value); 
        }
 
        ///  
        /// Run validation rules for the given step
        ///  
        internal override bool Validate(object value, ValidationStep validationStep)
        {
            // run rules attached to this binding
            bool result = base.Validate(value, validationStep); 

            if (validationStep == ValidationStep.UpdatedValue) 
            { 
                if (result && ParentBinding.ValidatesOnDataErrors)
                { 
                    // remember the old validation error, if it came from the implicit DataError rule
                    ValidationError oldValidationError = GetValidationErrors(validationStep);
                    if (oldValidationError != null &&
                        oldValidationError.RuleInError != DataErrorValidationRule.Instance) 
                    {
                        oldValidationError = null; 
                    } 

                    // run the DataError rule, even though it doesn't appear in the 
                    // ValidationRules collection
                    ValidationError error = RunValidationRule(DataErrorValidationRule.Instance, this, GetCulture());

                    if (error != null) 
                    {
                        UpdateValidationError(error); 
                        result = false; 
                    }
                    else if (oldValidationError != null) 
                    {
                        // the implicit rule is now valid - clear the old error
                        UpdateValidationError(null);
                    } 
                }
            } 
            else if (validationStep == ValidationStep.CommittedValue) 
            {
                if (result) 
                {
                    NeedsValidation = false;
                }
            } 

            return result; 
        } 

        ///  
        /// Run validation rules for the given step, and inform the binding group
        /// 
        internal override bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep)
        { 
            if (!NeedsValidation)
                return true; 
 
            object value;
            switch (validationStep) 
            {
                case ValidationStep.RawProposedValue:
                    value = GetRawProposedValue();
                    break; 
                case ValidationStep.ConvertedProposedValue:
                    value = bindingGroup.GetValue(this); 
                    break; 
                case ValidationStep.UpdatedValue:
                case ValidationStep.CommittedValue: 
                    value = this;
                    break;
                default:
                    throw new InvalidOperationException(SR.Get(SRID.ValidationRule_UnknownStep, validationStep, bindingGroup)); 
            }
 
            return Validate(value, validationStep); 
        }
 
        /// 
        /// Get the proposed value(s) that would be written to the source(s), applying
        /// conversion and checking UI-side validation rules.
        ///  
        internal override bool ValidateAndConvertProposedValue(out Collection values)
        { 
            Debug.Assert(NeedsValidation, "check NeedsValidation before calling this"); 
            values = null;
 
            // validate raw proposed value
            object rawValue = GetRawProposedValue();

            bool isValid = Validate(rawValue, ValidationStep.RawProposedValue); 

            // apply conversion and validate it 
            object convertedValue = isValid ? ConvertProposedValue(rawValue) 
                                            : DependencyProperty.UnsetValue;
 
            if (convertedValue == Binding.DoNothing)
            {
                convertedValue = DependencyProperty.UnsetValue;
            } 
            else if (convertedValue == DependencyProperty.UnsetValue)
            { 
                isValid = false; 
            }
            else 
            {
                isValid = Validate(convertedValue, ValidationStep.ConvertedProposedValue);
            }
 
            // return the result
            values = new Collection(); 
            values.Add(new ProposedValue(this, rawValue, convertedValue)); 
            return isValid;
        } 

        private bool IsValidValueForUpdate(object value, Type sourceType)
        {
            // null is always valid, even for value types.  The reflection layer 
            // apparently converts null to default(T).
            if (value == null) 
                return true; 

            // if direct assignment is possible, the value is valid 
            if (sourceType.IsAssignableFrom(value.GetType()))
                return true;

            // if the value is DBNull, ask the worker (answer depends on several factors) 
            if (Convert.IsDBNull(value))
                return Worker.IsDBNullValidForUpdate; 
 
            // otherwise the value is invalid
            return false; 
        }

        private void ProcessException(Exception ex, bool validate)
        { 
            object filteredException = null;
            ValidationError validationError = null; 
 
            // If there is not ExceptionFilter, then Wrap the
            // exception in a ValidationError. 
            if (ExceptionFilterExists())
            {
                filteredException = CallDoFilterException(ex);
 
                if (filteredException == null)
                    return; 
 
                validationError = filteredException as ValidationError;
            } 

            // See if an ExceptionValidationRule is in effect
            if (validationError == null && validate)
            { 
                ValidationRule exceptionValidationRule = ExceptionValidationRule.Instance;
 
                if (filteredException == null) 
                {
                    validationError = new ValidationError(exceptionValidationRule, this, ex.Message, ex); 
                }
                else
                {
                    validationError = new ValidationError(exceptionValidationRule, this, filteredException, ex); 
                }
            } 
 
            if (validationError != null)
            { 
                UpdateValidationError(validationError);
            }
        }
 
        // Sometimes a source update gets requested as a result of event leapfrogging,
        // where the binding has not yet been informed of a pending change to its 
        // path (e.g. Dev10 445406).  In this case, we should simply ignore the update. 
        private bool ShouldIgnoreUpdate()
        { 
            // The detection algorithm below is expensive, so only do when the target
            // property is especially susceptible to the problem
            if (TargetProperty.OwnerType != typeof(System.Windows.Controls.Primitives.Selector) &&  // SelectedItem, SelectedValue, SelectedIndex, etc.
                TargetProperty != ComboBox.TextProperty                                             // ComboBox.Text 
                )
            { 
                return false; 
            }
 
            // Re-evaluate the entire path.  If it doesn't produce the same source
            // object as our cached value, there is presumably a change notification
            // somewhere along the path that hasn't been delivered yet, due to event
            // leapfrogging. 

            // get initial (top-level) item 
            object item; 
            DependencyObject contextElement = ContextElement;
            if (contextElement == null) 
            {
                DependencyObject target = TargetElement;
                if (target != null && UsingMentor)
                { 
                    target = Helper.FindMentor(target);
                } 
                if (target == null) 
                {
                    return true; 
                }
                item = ParentBinding.SourceReference.GetDataObject(target,
                                                    new ObjectRefArgs() { ResolveNamesInTemplate = ResolveNamesInTemplate });
            } 
            else
            { 
                item = contextElement.GetValue(FrameworkElement.DataContextProperty); 
            }
 
            // Apply auto-magic rules for CVS, DSP, etc.
            // This logic should agree with Activate(item), except for event hookup.
            if (!ParentBinding.BindsDirectlyToSource)
            { 
                CollectionViewSource cvs;
                DataSourceProvider dsp; 
 
                if ((cvs = item as CollectionViewSource) != null)
                { 
                    item = cvs.CollectionView;
                }
                else if ((dsp = item as DataSourceProvider) != null)
                { 
                    item = dsp.Data;
                } 
            } 

            // If the top-level item is different, ignore the update 
            if (!Object.Equals(DataItem, item))
                return true;

            // check the rest of the path 
            return !Worker.IsPathCurrent();
        } 
#endregion Value 

#region Event handlers 

        private void OnDataContextChanged(DependencyObject contextElement)
        {
            // ADO BindingExpressions change the data context when a field changes. 
            // If the field is the one we're updating, ignore the DC change.
            if (!IsInUpdate && CanActivate) 
            { 
                if (IsReflective && RootBindingExpression.ParentBindingBase.BindingGroupName == String.Empty)
                { 
                    RejoinBindingGroup(IsReflective, contextElement);
                }

                object newItem = contextElement.GetValue(FrameworkElement.DataContextProperty); 
                if (!Object.Equals(DataItem, newItem))
                { 
                    Activate(newItem); 
                }
            } 
        }

        /// 
        /// Handle events from the centralized event table 
        /// 
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        { 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
            { 
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.GotEvent(
                                        TraceData.Identify(this),
                                        TraceData.IdentifyWeakEvent(managerType), 
                                        TraceData.Identify(sender)));
            } 
 
            if (managerType == typeof(CurrentChangingEventManager))
            { 
                Update(true);
                //
            }
            else if (managerType == typeof(CurrentChangedEventManager)) 
            {
                Worker.OnCurrentChanged(sender as ICollectionView, e); 
            } 
            else if (managerType == typeof(DataChangedEventManager))
            { 
                if (TraceLog != null)
                {
                    TraceLog.Add(" OnDataChanged from {0} at {1}", TraceLog.IdFor(_dataProvider), TraceLog.IdFor(this));
                } 
                Activate(sender);
            } 
            else if (managerType == typeof(LostFocusEventManager)) 
            {
                Update(true); 
            }
            else if (managerType == typeof(InheritanceContextChangedEventManager))
            {
                if (Status == BindingStatus.Unattached) 
                {
                    // retry bindings immediately when InheritanceContext changes, 
                    // so that triggers, animations, and rendering see the bound 
                    // value when they initialize their own local cache (bug DD 139838).
                    AttachToContext(AttachAttempt.Again); 
                    if (Status != BindingStatus.Unattached)
                    {
                        // if that worked, we don't need to run the task again
                        Engine.CancelTask(this, TaskOps.AttachToContext); 
                    }
                } 
                else 
                {
                    AttachToContext(AttachAttempt.Last); 
                }
            }
            else
            { 
                return false;       // unrecognized event
            } 
 
            return true;
        } 

#endregion Event handlers

#region Helper functions 

 
        // 
        // If this BindingExpression's ParentBinding has an ExceptionFilter set,
        // call it, otherwise give the MultiBinding (if there is one) 
        // a chance.
        //
        private object CallDoFilterException(Exception ex)
        { 
            if (ParentBinding.UpdateSourceExceptionFilter != null)
            { 
                return ParentBinding.DoFilterException(this, ex); 
            }
            else if (IsInMultiBindingExpression) 
            {
                return ParentMultiBindingExpression.ParentMultiBinding.DoFilterException(this, ex);
            }
 
            return null;
        } 
 
        private bool ExceptionFilterExists()
        { 
            return ( (ParentBinding.UpdateSourceExceptionFilter != null) ||
                     (IsInMultiBindingExpression && ParentMultiBindingExpression.ParentMultiBinding.UpdateSourceExceptionFilter != null)
                   );
        } 

 
        // surround any code that changes the value of a BindingExpression by 
        //      using (bindExpr.ChangingValue())
        //      { ... } 
        internal IDisposable ChangingValue()
        {
            return new ChangingValueHelper(this);
        } 

        // cancel any pending work 
        internal void CancelPendingTasks() 
        {
            Engine.CancelTasks(this); 
        }

        // replace this BindingExpression with a new one
        void Replace() 
        {
            DependencyObject target = TargetElement; 
            if (target != null) 
            {
                if (IsInBindingExpressionCollection) 
                    ParentBindingExpressionBase.ReplaceChild(this);
                else
                    BindingOperations.SetBinding(target, TargetProperty, ParentBinding);
            } 
        }
 
        // raise the TargetUpdated event (explicit polymorphism) 
        internal static void OnTargetUpdated(DependencyObject d, DependencyProperty dp)
        { 
            DataTransferEventArgs args = new DataTransferEventArgs(d, dp);
            args.RoutedEvent = Binding.TargetUpdatedEvent;
            FrameworkObject fo = new FrameworkObject(d);
 
            if (!fo.IsValid && d != null)
            { 
                fo.Reset(Helper.FindMentor(d)); 
            }
 
            fo.RaiseEvent(args);
        }

        // raise the SourceUpdatedEvent event (explicit polymorphism) 
        internal static void OnSourceUpdated(DependencyObject d, DependencyProperty dp)
        { 
            DataTransferEventArgs args = new DataTransferEventArgs(d, dp); 
            args.RoutedEvent = Binding.SourceUpdatedEvent;
            FrameworkObject fo = new FrameworkObject(d); 

            if (!fo.IsValid && d != null)
            {
                fo.Reset(Helper.FindMentor(d)); 
            }
 
            fo.RaiseEvent(args); 
        }
 
        internal override void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
        {
            DependencyProperty dp = args.Property;
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
            { 
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.GotPropertyChanged(
                                        TraceData.Identify(this), 
                                        TraceData.Identify(d),
                                        dp.Name));
            }
 
            if (dp == FrameworkElement.DataContextProperty)
            { 
                DependencyObject contextElement = ContextElement; 
                if (d == contextElement)
                { 
                    OnDataContextChanged(contextElement);
                }
            }
 
            if (dp == CollectionViewSource.ViewProperty)
            { 
                CollectionViewSource cvs = this.CollectionViewSource; 
                if (d == cvs)
                { 
                    Activate(cvs);
                }
            }
 
            if (dp == FrameworkElement.LanguageProperty && UsesLanguage && d == TargetElement)
            { 
                InvalidateCulture(); 
            }
 
            if (Worker != null)
            {
                Worker.OnSourceInvalidation(d, dp, args.IsASubPropertyChange);
            } 
        }
 
 
        private class ChangingValueHelper : IDisposable
        { 
            internal ChangingValueHelper(BindingExpression b)
            {
                _bindingExpression = b;
                b.CancelPendingTasks(); 
            }
 
            public void Dispose() 
            {
                _bindingExpression.TransferValue(); 
                GC.SuppressFinalize(this);
            }

            BindingExpression _bindingExpression; 
        }
 
        void SetDataItem(object newItem) 
        {
            _dataItem = CreateReference(newItem); 
        }

        // find the DataSource object (if any) that produced the DataContext
        // for element d 
        object GetDataSourceForDataContext(DependencyObject d)
        { 
            // look for ancestor that contributed the inherited value 
            DependencyObject ancestor;
            BindingExpression b = null; 

            for (ancestor = d;
                 ancestor != null;
                 ancestor = FrameworkElement.GetFrameworkParent(ancestor)) 
            {
                if (HasLocalDataContext(ancestor)) 
                { 
                    b = BindingOperations.GetBindingExpression(ancestor, FrameworkElement.DataContextProperty) as BindingExpression;
                    break; 
                }
            }

            if (b != null) 
                return b.DataSource;
 
            return null; 
        }
 
#endregion Helper functions

        //------------------------------------------------------
        // 
        //  Private Fields
        // 
        //----------------------------------------------------- 

        WeakReference           _ctxElement; 
        object                  _dataItem;
        BindingWorker           _worker;
        IValueConverter         _valueConverter;
        Type                    _sourceType; 
        DataSourceProvider      _dataProvider;
        object                  _collectionViewSource; 
        DynamicValueConverter   _dynamicConverter; 

        internal static readonly object NullDataItem = new NamedObject("NullDataItem"); 
        internal static readonly object IgnoreDefaultValue = new NamedObject("IgnoreDefaultValue");
    }

} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK