BindingExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / Data / BindingExpression.cs / 1 / 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.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, false); 
            }
        }

        //----------------------------------------------------- 
        //
        //  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");
 
            DependencyProperty dp = args.Property; 
            if (dp == null)
                throw new ArgumentNullException("dp"); 

            // 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 (relevant) 
            {
                relevant = (Worker != null) && (Worker.UsesDependencyProperty(d, dp)); 
            } 

            if (!relevant) 
                return;

            // if the notification arrived on the right Dispatcher, handle it now.
            if (Dispatcher.Thread == Thread.CurrentThread) 
            {
                HandlePropertyInvalidation(d, args); 
            } 
            else    // Otherwise, marshal it to the right Dispatcher.
            { 
                IsTransferPending = true;
                Dispatcher.BeginInvoke(
                    DispatcherPriority.DataBind,
                    new DispatcherOperationCallback(HandlePropertyInvalidationOperation), 
                    new object[]{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) 
                    return true;
 
                if (IsInUpdate) 
                {
                    // allow changes from an update to flow back to 
                    // the target if there's a converter or string format, and
                    // the binding isn't in "immediate" mode (bug 1207214)
                    return ((Converter == null && EffectiveStringFormat == null) || IsUpdateOnPropertyChanged);
                } 

                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 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)
        { 
            // this method is called when the last item in the path is replaced.
            // BindingGroup also wants to know about this. 
            BindingGroup bindingGroup = BindingGroup; 
            if (bindingGroup != null)
            { 
                bindingGroup.UpdateTable(this);
            }

            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)
        {
            return (d.ReadLocalValue(FrameworkElement.DataContextProperty) != DependencyProperty.UnsetValue); 
        }
 
        //------------------------------------------------------ 
        //
        //  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 void AttachOverride(DependencyObject target, DependencyProperty dp)
        {
            base.AttachOverride(target, dp);
 
            // 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)
        } 


        /// 
        /// 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
            if (IsUpdateOnLostFocus) 
            {
                LostFocusEventManager.RemoveListener(TargetElement, 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, 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)
            { 
                source = sourceRef.GetDataObject(mentor, traceObjectRef, ResolveNamesInTemplate);
 
                // 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 
            {
                // 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() 
        {
            LeaveBindingGroup();

            // 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, ResolveNamesInTemplate, false));
                    }
                }
            } 
            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; 
 
            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
            if (!IsOneWayToSource)
            {
                TransferValue(); 
            }
            else 
            { 
                UpdateValue();
            } 

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831)
        }
 
        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); 
        }
 
        // 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; 

            if (contextElement != null)
                ++size;
            if (cvs != null) 
                ++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);
            }

            // 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(NullDataItem, 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 = TargetProperty.PropertyType; 
            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 == NullDataItem) ? 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))); 
            } 

            // 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 IsCriticalException() 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.IsCriticalException(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 IsCriticalException() 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 
                if (CriticalExceptions.IsCriticalException(ex))
                    throw; 

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

                ProcessException(ex);
                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(NullDataItem, isASubPropertyChange);
        } 
 

        void OnTargetUpdated() 
        {
            if (NotifyOnTargetUpdated)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                { 
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression 
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression))   // not an inactive BindingExpression 
                    {
                        // 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 && this == 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)
        { 
            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))); 
            }

            return value;
        } 

        ///  
        /// Get the converted proposed value and inform the binding group 
        /// 
        internal override void ObtainConvertedProposedValue(BindingGroup bindingGroup) 
        {
            object value;

            if (NeedsUpdate) 
            {
                value = bindingGroup.GetValue(this); 
                if (value != DependencyProperty.UnsetValue) 
                {
                    value = ConvertProposedValue(value); 
                }
            }
            else
            { 
                value = BindingGroup.DeferredSourceValue;
            } 
 
            bindingGroup.SetValue(this, value);
        } 

        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)
            {
                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 IsCriticalException() 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) 
            { 
                if (CriticalExceptions.IsCriticalException(ex))
                    throw; 

                if (TraceData.IsEnabled)
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this, ex);
 
                ProcessException(ex);
                SetStatus(BindingStatus.UpdateSourceError); 
            } 
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled)
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this);

                SetStatus(BindingStatus.UpdateSourceError); 
            }
            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 void UpdateSource(BindingGroup bindingGroup) 
        {
            if (NeedsUpdate) 
            { 
                object value = bindingGroup.GetValue(this);
                value = UpdateSource(value); 
                bindingGroup.SetValue(this, value);
            }
        }
 
        /// 
        /// 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 (result && validationStep == ValidationStep.CommittedValue)
            { 
                if (ParentBinding.ValidatesOnDataErrors)
                { 
                    // 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;
                    } 
                } 

                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); 
        }
 
        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)
        {
            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 && ValidatesOnExceptions)
            {
                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) 
            {
                // use MarkInvalid rather than UpdateValidationErrors because 
                // this is essentially an explicit invalidation as this BindingExpression has
                // already passed all of the declared ValidationRules
                Validation.MarkInvalid(this, validationError);
            } 
        }
#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)
            { 
                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);
        }

        // invalidate the target property 
        void Invalidate(bool isASubPropertyChange)
        { 
            // don't invalidate during Attach.  The property engine does it 
            // already, and it would interfere with the on-demand activation
            // of style-defined BindingExpressions. 
            if (IsAttaching)
                return;

            DependencyObject target = TargetElement; 
            if (target != null)
            { 
                if (IsInBindingExpressionCollection) 
                    ParentBindingExpressionBase.InvalidateChild(this);
                else 
                {
                    if (TargetProperty != NoTargetProperty)
                    {
                        // recompute expression 
                        if (!isASubPropertyChange)
                        { 
                            target.InvalidateProperty(TargetProperty); 
                        }
                        else 
                        {
                            target.NotifySubPropertyChange(TargetProperty);
                        }
                    } 
                }
            } 
        } 

        // 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); 
        }
 
        private object HandlePropertyInvalidationOperation(object o) 
        {
            // This is the case where the source of the Binding belonged to a different Dispatcher 
            // than the target. For this scenario the source marshals off the invalidation information
            // onto the target's Dispatcher queue. This is where we unpack the marshalled information
            // to fire the invalidation on the target object.
 
            object[] args = (object[])o;
            HandlePropertyInvalidation((DependencyObject)args[0], (DependencyPropertyChangedEventArgs)args[1]); 
            return null; 
        }
 
        private 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 (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(); 
            }
 
            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.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, false); 
            }
        }

        //----------------------------------------------------- 
        //
        //  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");
 
            DependencyProperty dp = args.Property; 
            if (dp == null)
                throw new ArgumentNullException("dp"); 

            // 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 (relevant) 
            {
                relevant = (Worker != null) && (Worker.UsesDependencyProperty(d, dp)); 
            } 

            if (!relevant) 
                return;

            // if the notification arrived on the right Dispatcher, handle it now.
            if (Dispatcher.Thread == Thread.CurrentThread) 
            {
                HandlePropertyInvalidation(d, args); 
            } 
            else    // Otherwise, marshal it to the right Dispatcher.
            { 
                IsTransferPending = true;
                Dispatcher.BeginInvoke(
                    DispatcherPriority.DataBind,
                    new DispatcherOperationCallback(HandlePropertyInvalidationOperation), 
                    new object[]{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) 
                    return true;
 
                if (IsInUpdate) 
                {
                    // allow changes from an update to flow back to 
                    // the target if there's a converter or string format, and
                    // the binding isn't in "immediate" mode (bug 1207214)
                    return ((Converter == null && EffectiveStringFormat == null) || IsUpdateOnPropertyChanged);
                } 

                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 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)
        { 
            // this method is called when the last item in the path is replaced.
            // BindingGroup also wants to know about this. 
            BindingGroup bindingGroup = BindingGroup; 
            if (bindingGroup != null)
            { 
                bindingGroup.UpdateTable(this);
            }

            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)
        {
            return (d.ReadLocalValue(FrameworkElement.DataContextProperty) != DependencyProperty.UnsetValue); 
        }
 
        //------------------------------------------------------ 
        //
        //  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 void AttachOverride(DependencyObject target, DependencyProperty dp)
        {
            base.AttachOverride(target, dp);
 
            // 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)
        } 


        /// 
        /// 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
            if (IsUpdateOnLostFocus) 
            {
                LostFocusEventManager.RemoveListener(TargetElement, 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, 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)
            { 
                source = sourceRef.GetDataObject(mentor, traceObjectRef, ResolveNamesInTemplate);
 
                // 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 
            {
                // 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() 
        {
            LeaveBindingGroup();

            // 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, ResolveNamesInTemplate, false));
                    }
                }
            } 
            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; 
 
            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
            if (!IsOneWayToSource)
            {
                TransferValue(); 
            }
            else 
            { 
                UpdateValue();
            } 

            GC.KeepAlive(target);   // keep target alive during activation (bug 956831)
        }
 
        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); 
        }
 
        // 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; 

            if (contextElement != null)
                ++size;
            if (cvs != null) 
                ++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);
            }

            // 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(NullDataItem, 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 = TargetProperty.PropertyType; 
            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 == NullDataItem) ? 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))); 
            } 

            // 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 IsCriticalException() 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.IsCriticalException(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 IsCriticalException() 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 
                if (CriticalExceptions.IsCriticalException(ex))
                    throw; 

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

                ProcessException(ex);
                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(NullDataItem, isASubPropertyChange);
        } 
 

        void OnTargetUpdated() 
        {
            if (NotifyOnTargetUpdated)
            {
                DependencyObject target = TargetElement; 
                if (target != null)
                { 
                    if (    !IsInMultiBindingExpression           // not an inner BindingExpression 
                        &&  (   !IsInPriorityBindingExpression
                            ||  this == ParentPriorityBindingExpression.ActiveBindingExpression))   // not an inactive BindingExpression 
                    {
                        // 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 && this == 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)
        { 
            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))); 
            }

            return value;
        } 

        ///  
        /// Get the converted proposed value and inform the binding group 
        /// 
        internal override void ObtainConvertedProposedValue(BindingGroup bindingGroup) 
        {
            object value;

            if (NeedsUpdate) 
            {
                value = bindingGroup.GetValue(this); 
                if (value != DependencyProperty.UnsetValue) 
                {
                    value = ConvertProposedValue(value); 
                }
            }
            else
            { 
                value = BindingGroup.DeferredSourceValue;
            } 
 
            bindingGroup.SetValue(this, value);
        } 

        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)
            {
                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 IsCriticalException() 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) 
            { 
                if (CriticalExceptions.IsCriticalException(ex))
                    throw; 

                if (TraceData.IsEnabled)
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this, ex);
 
                ProcessException(ex);
                SetStatus(BindingStatus.UpdateSourceError); 
            } 
            catch // non CLS compliant exception
            { 
                if (TraceData.IsEnabled)
                    TraceData.Trace(TraceEventType.Error, TraceData.WorkerUpdateFailed, this);

                SetStatus(BindingStatus.UpdateSourceError); 
            }
            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 void UpdateSource(BindingGroup bindingGroup) 
        {
            if (NeedsUpdate) 
            { 
                object value = bindingGroup.GetValue(this);
                value = UpdateSource(value); 
                bindingGroup.SetValue(this, value);
            }
        }
 
        /// 
        /// 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 (result && validationStep == ValidationStep.CommittedValue)
            { 
                if (ParentBinding.ValidatesOnDataErrors)
                { 
                    // 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;
                    } 
                } 

                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); 
        }
 
        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)
        {
            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 && ValidatesOnExceptions)
            {
                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) 
            {
                // use MarkInvalid rather than UpdateValidationErrors because 
                // this is essentially an explicit invalidation as this BindingExpression has
                // already passed all of the declared ValidationRules
                Validation.MarkInvalid(this, validationError);
            } 
        }
#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)
            { 
                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);
        }

        // invalidate the target property 
        void Invalidate(bool isASubPropertyChange)
        { 
            // don't invalidate during Attach.  The property engine does it 
            // already, and it would interfere with the on-demand activation
            // of style-defined BindingExpressions. 
            if (IsAttaching)
                return;

            DependencyObject target = TargetElement; 
            if (target != null)
            { 
                if (IsInBindingExpressionCollection) 
                    ParentBindingExpressionBase.InvalidateChild(this);
                else 
                {
                    if (TargetProperty != NoTargetProperty)
                    {
                        // recompute expression 
                        if (!isASubPropertyChange)
                        { 
                            target.InvalidateProperty(TargetProperty); 
                        }
                        else 
                        {
                            target.NotifySubPropertyChange(TargetProperty);
                        }
                    } 
                }
            } 
        } 

        // 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); 
        }
 
        private object HandlePropertyInvalidationOperation(object o) 
        {
            // This is the case where the source of the Binding belonged to a different Dispatcher 
            // than the target. For this scenario the source marshals off the invalidation information
            // onto the target's Dispatcher queue. This is where we unpack the marshalled information
            // to fire the invalidation on the target object.
 
            object[] args = (object[])o;
            HandlePropertyInvalidation((DependencyObject)args[0], (DependencyPropertyChangedEventArgs)args[1]); 
            return null; 
        }
 
        private 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 (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(); 
            }
 
            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