BindingExpressionBase.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Framework / System / Windows / Data / BindingExpressionBase.cs / 4 / BindingExpressionBase.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Defines BindingExpressionBase object, 
//              base class for BindingExpression, PriorityBindingExpression, 
//              and MultiBindingExpression.
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
 
// build with this symbol defined to catch errors about not using
// BindingExpression.GetReference correctly 
//#define USE_ITEM_REFERENCE 

using System; 
using System.Collections.ObjectModel;   // Collection
using System.ComponentModel;        // TypeConverter
using System.Diagnostics;           // StackTrace
using System.Globalization;         // CultureInfo 

using System.Windows;               // FrameworkElement 
using System.Windows.Controls;      // Validation 
using System.Windows.Markup;        // XmlLanguage
using System.Windows.Threading;     // Dispatcher 
using MS.Internal;                  // Invariant.Assert
using MS.Internal.Controls;         // ValidationErrorCollection
using MS.Internal.Data;             // DataBindEngine
using MS.Internal.KnownBoxes;       // BooleanBoxes 
using MS.Internal.Utility;          // TraceLog
 
namespace System.Windows.Data 
{
 
    /// 
    /// Base class for Binding Expressions.
    /// 
    public abstract class BindingExpressionBase : Expression, IWeakEventListener 
    {
 
        // Flags indicating run-time properties of a BindingExpression 
        [Flags]
        internal enum BindingFlags 
        {
            // names used by Binding

            OneWay                  = PrivateFlags.iSourceToTarget, 
            TwoWay                  = PrivateFlags.iSourceToTarget | PrivateFlags.iTargetToSource,
            OneWayToSource          = PrivateFlags.iTargetToSource, 
            OneTime                 = 0, 
            PropDefault             = PrivateFlags.iPropDefault,
            NotifyOnTargetUpdated   = PrivateFlags.iNotifyOnTargetUpdated, 
            NotifyOnSourceUpdated   = PrivateFlags.iNotifyOnSourceUpdated,
            NotifyOnValidationError = PrivateFlags.iNotifyOnValidationError,
            UpdateOnPropertyChanged = 0,
            UpdateOnLostFocus       = PrivateFlags.iUpdateOnLostFocus, 
            UpdateExplicitly        = PrivateFlags.iUpdateExplicitly,
            UpdateDefault           = PrivateFlags.iUpdateDefault, 
            PathGeneratedInternally = PrivateFlags.iPathGeneratedInternally, 
            ValidatesOnExceptions   = PrivateFlags.iValidatesOnExceptions,
            ValidatesOnDataErrors   = PrivateFlags.iValidatesOnDataErrors, 

            Default                 = PropDefault | UpdateDefault,

            ///  Error value, returned by FlagsFrom to indicate faulty input 
            IllegalInput                = PrivateFlags.iIllegalInput,
 
            PropagationMask = OneWay | TwoWay | OneWayToSource | OneTime | PropDefault, 
            UpdateMask      = UpdateOnPropertyChanged | UpdateOnLostFocus | UpdateExplicitly | UpdateDefault,
        } 

        [Flags]
        private enum PrivateFlags
        { 
            // internal use
 
            iSourceToTarget             = 0x00000001, 
            iTargetToSource             = 0x00000002,
            iPropDefault                = 0x00000004, 
            iNotifyOnTargetUpdated      = 0x00000008,
            iDefaultValueConverter      = 0x00000010,
            iInTransfer                 = 0x00000020,
            iInUpdate                   = 0x00000040, 
            iTransferPending            = 0x00000080,
            iNeedDataTransfer           = 0x00000100, 
            iTransferDeferred           = 0x00000200,   // used by MultiBindingExpression 
            iUpdateOnLostFocus          = 0x00000400,
            iUpdateExplicitly           = 0x00000800, 
            iUpdateDefault              = iUpdateExplicitly | iUpdateOnLostFocus,
            iNeedUpdate                 = 0x00001000,
            iPathGeneratedInternally    = 0x00002000,
            iUsingMentor                = 0x00004000, 
            iResolveNamesInTemplate     = 0x00008000,
            iDetaching                  = 0x00010000, 
            iNeedsCollectionView        = 0x00020000, 
            iInPriorityBindingExpression= 0x00040000,
            iInMultiBindingExpression   = 0x00080000, 
            iUsingFallbackValue         = 0x00100000,
            iNotifyOnValidationError    = 0x00200000,
            iAttaching                  = 0x00400000,
            iNotifyOnSourceUpdated      = 0x00800000, 
            iValidatesOnExceptions      = 0x01000000,
            iValidatesOnDataErrors      = 0x02000000, 
            iIllegalInput               = 0x04000000, 
            iNeedsValidation            = 0x08000000,
 
            iPropagationMask = iSourceToTarget | iTargetToSource | iPropDefault,
            iUpdateMask      = iUpdateOnLostFocus | iUpdateExplicitly,
        }
 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        ///  Constructor 
        internal BindingExpressionBase(BindingBase binding, BindingExpressionBase parent) : base(ExpressionMode.SupportsUnboundSources)
        { 
            if (binding == null)
                throw new ArgumentNullException("binding"); 
 
            _binding = binding;
            _parentBindingExpression = parent; 

            _flags = (PrivateFlags)binding.Flags;

            if (parent != null) 
            {
                ResolveNamesInTemplate = parent.ResolveNamesInTemplate; 
 
                Type type = parent.GetType();
                if (type == typeof(MultiBindingExpression)) 
                    ChangeFlag(PrivateFlags.iInMultiBindingExpression, true);
                else if (type == typeof(PriorityBindingExpression))
                    ChangeFlag(PrivateFlags.iInPriorityBindingExpression, true);
            } 

            // initialize tracing information 
            PresentationTraceLevel traceLevel = PresentationTraceSources.GetTraceLevel(binding); 

            if (traceLevel > 0) 
            {
                // copy TraceLevel from parent BindingBase - it can be changed later
                PresentationTraceSources.SetTraceLevel(this, traceLevel);
            } 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.CreateExpression)) 
            { 
                if (parent == null)
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.CreatedExpression(
                                            TraceData.Identify(this),
                                            TraceData.Identify(binding))); 
                }
                else 
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.CreatedExpressionInParent( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(binding),
                                            TraceData.Identify(parent)));
                } 
            }
 
            if (LookupValidationRule(typeof(ExceptionValidationRule)) != null) 
            {
                ChangeFlag(PrivateFlags.iValidatesOnExceptions, true); 
            }

            if (LookupValidationRule(typeof(DataErrorValidationRule)) != null)
            { 
                ChangeFlag(PrivateFlags.iValidatesOnDataErrors, true);
            } 
        } 

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

        ///  Binding from which this expression was created  
        public BindingBase  ParentBindingBase  { get { return _binding; } } 

        /// Status of the BindingExpression 
        public BindingStatus Status { get { return _status; } }

        /// 
        ///     The ValidationError that caused this 
        ///     BindingExpression to be invalid.
        ///  
        public virtual ValidationError ValidationError 
        {
            get 
            {
                return _validationError;
            }
        } 

        ///  
        ///     HasError returns true if any of the ValidationRules 
        ///     in the ParentBinding failed its validation rule.
        ///  
        public virtual bool HasError
        {
            get
            { 
                return _validationError != null;
            } 
        } 

        //------------------------------------------------------ 
        //
        //  Public Methods
        //
        //------------------------------------------------------ 

        ///  Force a data transfer from source to target  
        public virtual void UpdateTarget() 
        {
        } 

        ///  Send the current value back to the source 
        ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource 
        public virtual void UpdateSource() 
        {
        } 
 
#region Expression overrides
 
        /// 
        ///     Notification that the Expression has been set as a property's value
        /// 
        ///  
        ///     Subclasses should not override OnAttach(), but must override Attach()
        ///  
        /// DependencyObject being set 
        /// Property being set
        internal sealed override void OnAttach(DependencyObject d, DependencyProperty dp) 
        {
            if (d == null)
                throw new ArgumentNullException("d");
            if (dp == null) 
                throw new ArgumentNullException("dp");
 
            Attach(d, dp); 
        }
 
        /// 
        ///     Notification that the Expression has been removed as a property's value
        /// 
        ///  
        ///     Subclasses should not override OnDetach(), but must override Detach()
        ///  
        /// DependencyObject being cleared 
        /// Property being cleared
        internal sealed override void OnDetach(DependencyObject d, DependencyProperty dp) 
        {
            Detach();
        }
 
        /// 
        ///     List of sources of the Expression 
        ///  
        /// Sources list
        internal override DependencySource[] GetSources() 
        {
            int j, k;
            int n = (_sources != null) ? _sources.Length : 0;
            if (n == 0) 
                return null;
 
            DependencySource[] result = new DependencySource[n]; 

            // convert the weak references into strong ones 
            for (j=0, k=0; k 
        /// Handle events from the centralized event table
        ///  
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        {
            return ReceiveWeakEvent(managerType, sender, e); 
        }

#region BindingExpressions with no target DP
 
        //-----------------------------------------------------
        // 
        //  API for BindingExpressions with no target DP (task 20769) 
        //  This is internal for now, until we review whether we wish to
        //  make it public 
        //
        //------------------------------------------------------

        ///  Create an untargeted BindingExpression  
        internal static BindingExpressionBase CreateUntargetedBindingExpression(DependencyObject d, BindingBase binding)
        { 
            return binding.CreateBindingExpression(d, NoTargetProperty); 
        }
 
        ///  Attach the BindingExpression to its target element 
        /// 
        /// This method must be called once during the initialization.
        ///  
        /// The target element 
        internal void Attach(DependencyObject d) 
        { 
            Attach(d, NoTargetProperty);
        } 

        ///  This event is raised when the BindingExpression's value changes 
        internal event EventHandler ValueChanged;
 
        /* The following APIs are also needed for untargeted bindings, but they already exist
        for other reasons. 
 
        ///  The current value of the BindingExpression 
        internal object Value { get; set; } 

        ///  Activate the BindingExpression, using the given item as its root item. 
        internal void Activate(object item) {}
 
        ///  Deactivate the BindingExpression. 
        internal void Deactivate() {} 
 
        ///  Detach the BindingExpression from its target element 
        ///  
        /// This method must be called once when the BindingExpression is no longer needed.
        /// 
        internal void Detach() {}
 
        */
 
#endregion BindingExpressions with no target DP 

        //----------------------------------------------------- 
        //
        //  Protected Properties
        //
        //----------------------------------------------------- 

        ///  True if this binding expression is attaching  
        internal bool IsAttaching 
        {
            get { return TestFlag(PrivateFlags.iAttaching); } 
            set { ChangeFlag(PrivateFlags.iAttaching, value); }
        }

        ///  True if this binding expression is detaching  
        internal bool IsDetaching
        { 
            get { return TestFlag(PrivateFlags.iDetaching); } 
            set { ChangeFlag(PrivateFlags.iDetaching, value); }
        } 

        ///  True if this binding expression updates the target 
        internal bool IsDynamic
        { 
            get
            { 
                return (    TestFlag(PrivateFlags.iSourceToTarget) 
                        &&  (!IsInMultiBindingExpression || ParentMultiBindingExpression.IsDynamic));
            } 
        }

        ///  True if this binding expression updates the source 
        internal bool IsReflective 
        {
            get 
            { 
                return (    TestFlag(PrivateFlags.iTargetToSource)
                        &&  (!IsInMultiBindingExpression || ParentMultiBindingExpression.IsReflective)); 
            }
            set { ChangeFlag(PrivateFlags.iTargetToSource, value); }
        }
 
        ///  True if this binding expression uses a default ValueConverter 
        internal bool UseDefaultValueConverter 
        { 
            get { return TestFlag(PrivateFlags.iDefaultValueConverter); }
            set { ChangeFlag(PrivateFlags.iDefaultValueConverter, value); } 
        }

        ///  True if this binding expression is OneWayToSource 
        internal bool IsOneWayToSource 
        {
            get { return (_flags & PrivateFlags.iPropagationMask) == PrivateFlags.iTargetToSource; } 
        } 

        ///  True if this binding expression updates on PropertyChanged  
        internal bool IsUpdateOnPropertyChanged
        {
            get { return (_flags & PrivateFlags.iUpdateMask) == 0; }
        } 

        ///  True if this binding expression updates on LostFocus  
        internal bool IsUpdateOnLostFocus 
        {
            get { return TestFlag(PrivateFlags.iUpdateOnLostFocus); } 
        }

        ///  True if this binding expression has a pending target update 
        internal bool IsTransferPending 
        {
            get { return TestFlag(PrivateFlags.iTransferPending); } 
            set { ChangeFlag(PrivateFlags.iTransferPending, value); } 
        }
 
        ///  True if this binding expression is deferring a target update 
        internal bool TransferIsDeferred
        {
            get { return TestFlag(PrivateFlags.iTransferDeferred); } 
            set { ChangeFlag(PrivateFlags.iTransferDeferred, value); }
        } 
 
        ///  True if this binding expression is updating the target 
        internal bool IsInTransfer 
        {
            get { return TestFlag(PrivateFlags.iInTransfer); }
            set { ChangeFlag(PrivateFlags.iInTransfer, value); }
        } 

        ///  True if this binding expression is updating the source  
        internal bool IsInUpdate 
        {
            get { return TestFlag(PrivateFlags.iInUpdate); } 
            set { ChangeFlag(PrivateFlags.iInUpdate, value); }
        }

        ///  True if this binding expression is using the fallback value  
        internal bool UsingFallbackValue
        { 
            get { return TestFlag(PrivateFlags.iUsingFallbackValue); } 
            set { ChangeFlag(PrivateFlags.iUsingFallbackValue, value); }
        } 

        ///  True if this binding expression uses the mentor of the target element 
        internal bool UsingMentor
        { 
            get { return TestFlag(PrivateFlags.iUsingMentor); }
            set { ChangeFlag(PrivateFlags.iUsingMentor, value); } 
        } 

        ///  True if this binding expression should resolve ElementName within the template of the target element  
        internal bool ResolveNamesInTemplate
        {
            get { return TestFlag(PrivateFlags.iResolveNamesInTemplate); }
            set { ChangeFlag(PrivateFlags.iResolveNamesInTemplate, value); } 
        }
 
        ///  True if this binding expression has a pending target update  
        internal bool NeedsDataTransfer
        { 
            get { return TestFlag(PrivateFlags.iNeedDataTransfer); }
            set { ChangeFlag(PrivateFlags.iNeedDataTransfer, value); }
        }
 
        ///  True if this binding expression has a pending source update 
        internal bool NeedsUpdate 
        { 
            get { return TestFlag(PrivateFlags.iNeedUpdate); }
            set 
            {
                ChangeFlag(PrivateFlags.iNeedUpdate, value);
                if (value)
                { 
                    NeedsValidation = true;
                } 
            } 
        }
 
        ///  True if this binding expression needs validation 
        internal bool NeedsValidation
        {
            get { return TestFlag(PrivateFlags.iNeedsValidation); } 
            set { ChangeFlag(PrivateFlags.iNeedsValidation, value); }
        } 
 
        ///  True if this binding expression should raise the TargetUpdated event 
        internal bool NotifyOnTargetUpdated 
        {
            get { return TestFlag(PrivateFlags.iNotifyOnTargetUpdated); }
            set { ChangeFlag(PrivateFlags.iNotifyOnTargetUpdated, value); }
        } 

        ///  True if this binding expression should raise the SourceUpdated event  
        internal bool NotifyOnSourceUpdated 
        {
            get { return TestFlag(PrivateFlags.iNotifyOnSourceUpdated); } 
            set { ChangeFlag(PrivateFlags.iNotifyOnSourceUpdated, value); }
        }

        ///  True if this binding expression should raise the ValidationError event  
        internal bool NotifyOnValidationError
        { 
            get { return TestFlag(PrivateFlags.iNotifyOnValidationError); } 
            set { ChangeFlag(PrivateFlags.iNotifyOnValidationError, value); }
        } 

        ///  True if this binding expression belongs to a PriorityBinding 
        internal bool IsInPriorityBindingExpression
        { 
            get { return TestFlag(PrivateFlags.iInPriorityBindingExpression); }
        } 
 
        ///  True if this binding expression belongs to a MultiBinding 
        internal bool IsInMultiBindingExpression 
        {
            get { return TestFlag(PrivateFlags.iInMultiBindingExpression); }
        }
 
        ///  True if this binding expression belongs to a PriorityBinding or MultiBinding 
        internal bool IsInBindingExpressionCollection 
        { 
            get { return TestFlag(PrivateFlags.iInPriorityBindingExpression | PrivateFlags.iInMultiBindingExpression); }
        } 

        ///  True if this binding expression validates on exceptions 
        internal bool ValidatesOnExceptions
        { 
            get { return TestFlag(PrivateFlags.iValidatesOnExceptions); }
        } 
 
        ///  True if this binding expression validates on data errors 
        internal bool ValidatesOnDataErrors 
        {
            get { return TestFlag(PrivateFlags.iValidatesOnDataErrors); }
        }
 
        ///  The parent MultiBindingExpression (if any) 
        internal MultiBindingExpression ParentMultiBindingExpression 
        { 
            get { return _parentBindingExpression as MultiBindingExpression; }
        } 

        ///  The parent PriorityBindingExpression (if any) 
        internal PriorityBindingExpression ParentPriorityBindingExpression
        { 
            get { return _parentBindingExpression as PriorityBindingExpression; }
        } 
 
        ///  The parent PriorityBindingExpression or MultiBindingExpression (if any) 
        internal BindingExpressionBase ParentBindingExpressionBase 
        {
            get { return _parentBindingExpression; }
        }
 
        ///  The FallbackValue (from the parent Binding), possibly converted
        /// to a type suitable for the target property. 
        internal object FallbackValue 
        {
            // perf note: we recompute the value every time it's needed.  This is 
            // a good decision if we seldom need the value.  Alternatively we could
            // cache it.  Wait until we know what the perf impact really is.
            get { return ConvertFallbackValue(ParentBindingBase.FallbackValue, TargetProperty, this); }
        } 

        ///  The default value of the target property  
        internal object DefaultValue 
        {
            // perf note: we recompute the value every time it's needed.  This is 
            // a good decision if we seldom need the value.  Alternatively we could
            // cache it.  Wait until we know what the perf impact really is.
            get
            { 
                DependencyObject target = TargetElement;
                if (target != null) 
                { 
                    return TargetProperty.GetDefaultValue(target.DependencyObjectType);
                } 
                return DependencyProperty.UnsetValue;
            }
        }
 
        ///  The effective string format, taking into account the target
        /// property, parent bindings, convenience syntax, etc.  
        internal string EffectiveStringFormat 
        {
            get { return _effectiveStringFormat; } 
        }

        ///  The effective TargetNullValue, taking into account the target
        /// property, parent bindings, etc.  
        internal object EffectiveTargetNullValue
        { 
            get { return _effectiveTargetNullValue; } 
        }
 
        ///  return the root of the tree of {Multi/Priority}BindingExpressions
        internal BindingExpressionBase RootBindingExpression
        {
            get 
            {
                BindingExpressionBase child = this; 
                BindingExpressionBase parent = this.ParentBindingExpressionBase; 
                while (parent != null)
                { 
                    child = parent;
                    parent = child.ParentBindingExpressionBase;
                }
                return child; 
            }
        } 
 
        ///  return the binding group to which this expression belongs (or null) 
        internal BindingGroup BindingGroup 
        {
            get
            {
                BindingExpressionBase root = RootBindingExpression; 
                WeakReference wr = root._bindingGroup;
                return (wr == null) ? null : (BindingGroup)wr.Target; 
            } 
        }
 
        internal virtual bool IsParentBindingUpdateTriggerDefault
        {
            get { return false; }
        } 

        //----------------------------------------------------- 
        // 
        //  Protected Methods
        // 
        //------------------------------------------------------

        /// 
        /// Attach the binding expression to the given target object and property. 
        /// Derived classes should call base.AttachOverride before doing their work.
        ///  
        internal virtual void AttachOverride(DependencyObject target, DependencyProperty dp) 
        {
            _targetElement = new WeakReference(target); 
            _targetProperty = dp;

            // get the engine
            _engine = DataBindEngine.CurrentDataBindEngine; 

            DetermineEffectiveStringFormat(); 
            DetermineEffectiveTargetNullValue(); 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach)) 
            {
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.AttachExpression(
                                        TraceData.Identify(this), 
                                        target.GetType().FullName, dp.Name, AvTrace.GetHashCodeHelper(target)));
            } 
        } 

        ///  
        /// Detach the binding expression from its target object and property.
        /// Derived classes should call base.DetachOverride after doing their work.
        /// 
        internal virtual void DetachOverride() 
        {
            _engine = null; 
            _targetElement = null; 
            _targetProperty = null;
            SetStatus(BindingStatus.Detached); 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach))
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.DetachExpression(
                                        TraceData.Identify(this))); 
            } 
        }
 
        /// 
        /// Invalidate the given child expression.
        /// 
        internal abstract void InvalidateChild(BindingExpressionBase bindingExpression); 

        ///  
        /// Change the dependency sources for the given child expression. 
        /// 
        internal abstract void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources); 

        /// 
        /// Replace the given child expression with a new one.
        ///  
        internal abstract void ReplaceChild(BindingExpressionBase bindingExpression);
 
        // handle joining or leaving a binding group 
        internal void OnBindingGroupChanged(bool joining)
        { 
            if (joining)
            {
                // joining a binding group:
                // update Explicitly, unless declared otherwise 
                if (IsParentBindingUpdateTriggerDefault)
                { 
                    if (IsUpdateOnLostFocus) 
                    {
                        LostFocusEventManager.RemoveListener(TargetElement, this); 
                    }

                    SetUpdateSourceTrigger(UpdateSourceTrigger.Explicit);
                } 
            }
            else 
            { 
                // leaving a binding group:
                // restore update trigger 
                if (IsParentBindingUpdateTriggerDefault)
                {
                    FrameworkPropertyMetadata fwMetaData = TargetProperty.GetMetadata(TargetElement.DependencyObjectType) as FrameworkPropertyMetadata;
 
                    UpdateSourceTrigger ust = GetDefaultUpdateSourceTrigger(fwMetaData);
                    SetUpdateSourceTrigger(ust); 
 
                    if (IsUpdateOnLostFocus)
                    { 
                        LostFocusEventManager.AddListener(TargetElement, this);
                    }
                }
            } 
        }
 
        // register the leaf bindings with the binding group 
        internal abstract void UpdateBindingGroup(BindingGroup bg);
 
        // transfer a value from target to source
        internal void UpdateValue()
        {
            UpdateValidationError(null); 

            object value = GetRawProposedValue(); 
            if (!Validate(value, ValidationStep.RawProposedValue)) 
                return;
 
            value = ConvertProposedValue(value);
            if (!Validate(value, ValidationStep.ConvertedProposedValue))
                return;
 
            value = UpdateSource(value);
            if (!Validate(value, ValidationStep.UpdatedValue)) 
                return; 

            value = CommitSource(value); 
            if (!Validate(value, ValidationStep.CommittedValue))
                return;

            EndSourceUpdate(); 
        }
 
        ///  
        /// Get the raw proposed value
        ///  
        internal virtual object GetRawProposedValue()
        {
            object value = Value;
 
            // TargetNullValue is the UI representation of a "null" value.  Use null internally.
            if (Object.Equals(value, EffectiveTargetNullValue)) 
            { 
                value = null;
            } 

            return value;
        }
 
        /// 
        /// Get the converted proposed value 
        ///  
        internal abstract object ConvertProposedValue(object rawValue);
 
        /// 
        /// Get the converted proposed value and inform the binding group
        /// 
        internal abstract void ObtainConvertedProposedValue(BindingGroup bindingGroup); 

        ///  
        /// Update the source value 
        /// 
        internal abstract object UpdateSource(object convertedValue); 

        /// 
        /// Update the source value and inform the binding group
        ///  
        internal abstract void UpdateSource(BindingGroup bindingGroup);
 
        ///  
        /// Commit the source value
        ///  
        internal virtual object CommitSource(object value)
        {
            return value;
        } 

        ///  
        /// Store the value in the binding group 
        /// 
        internal abstract void StoreValueInBindingGroup(object value, BindingGroup bindingGroup); 

        /// 
        /// Run validation rules for the given step
        ///  
        internal virtual bool Validate(object value, ValidationStep validationStep)
        { 
            if (value == Binding.DoNothing || value == DependencyProperty.UnsetValue) 
                return true;
 
            // clear errors from this step - we're about to reevaluate those rules
            ClearValidationErrors(validationStep);

            Collection validationRules = ParentBindingBase.ValidationRulesInternal; 

            if (validationRules != null) 
            { 
                CultureInfo culture = GetCulture();
                switch (validationStep) 
                {
                    case ValidationStep.UpdatedValue:
                    case ValidationStep.CommittedValue:
                        // rules at these steps get passed the rule owner 
                        value = this;
                        break; 
                } 

                foreach (ValidationRule validationRule in validationRules) 
                {
                    if (validationRule.ValidationStep == validationStep)
                    {
                        ValidationResult validationResult = validationRule.Validate(value, culture); 

                        if (!validationResult.IsValid) 
                        { 
                            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update))
                            { 
                                TraceData.Trace(TraceEventType.Warning,
                                                    TraceData.ValidationRuleFailed(
                                                        TraceData.Identify(this),
                                                        TraceData.Identify(validationRule))); 
                            }
 
                            UpdateValidationError( new ValidationError(validationRule, this, validationResult.ErrorContent, null)); 
                            return false; // kenlai:
                        } 
                    }
                }
            }
 
            return true;
        } 
 
        /// 
        /// Run validation rules for the given step, and inform the binding group 
        /// 
        internal abstract bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep);

        ///  
        /// Compute the culture, either from the parent Binding, or from the target element.
        ///  
        internal CultureInfo GetCulture() 
        {
            // lazy initialization, to let the target element acquire all its properties 
            if (_culture == DefaultValueObject)
            {
                // explicit culture set in Binding
                _culture = ParentBindingBase.ConverterCultureInternal; 

                // if that doesn't work, use target element's xml:lang property 
                if (_culture == null) 
                {
                    DependencyObject target = TargetElement; 
                    if (target != null)
                    {
                        if (IsInTransfer && (TargetProperty == FrameworkElement.LanguageProperty))
                        { 
                            // A binding for the Language property needs the value
                            // of the Language property.  This circularity is not 
                            // supported (bug 1274874). 
                            if (TraceData.IsEnabled)
                            { 
                                TraceData.Trace(TraceEventType.Critical, TraceData.RequiresExplicitCulture, TargetProperty.Name, this);
                            }

                            throw new InvalidOperationException(SR.Get(SRID.RequiresExplicitCulture, TargetProperty.Name)); 
                        }
 
                        // cache CultureInfo since requerying an inheritable property on every Transfer/Update can be quite expensive 
                        // CultureInfo DP rarely changes once a XAML document is loaded.
                        // To be 100% correct, changes to the CultureInfo attached DP should be tracked 
                        // and cause a re-evaluation of this binding.
                        _culture = ((XmlLanguage) target.GetValue(FrameworkElement.LanguageProperty)).GetSpecificCulture();
                    }
                } 
            }
            return (CultureInfo)_culture; 
        } 

        ///  Begin a source update  
        internal void BeginSourceUpdate()
        {
            ChangeFlag(PrivateFlags.iInUpdate, true);
        } 

        ///  End a source update  
        internal void EndSourceUpdate() 
        {
            ChangeFlag(PrivateFlags.iInUpdate | PrivateFlags.iNeedUpdate, false); 
        }

        ///  change the value to the new value, and notify listeners 
        internal void ChangeValue(object newValue, bool notify) 
        {
            object oldValue = (_value != DefaultValueObject) ? _value : DependencyProperty.UnsetValue; 
 
            _value = newValue;
 
            if (notify && ValueChanged != null)
            {
                ValueChanged(this, new BindingValueChangedEventArgs(oldValue, newValue));
            } 
        }
 
        ///  the target value has changed - the source needs to be updated  
        internal void Dirty()
        { 
            if (!IsInTransfer)
            {
                NeedsUpdate = true;
                if (IsUpdateOnPropertyChanged) 
                    Update(true);
            } 
        } 

        ///  use the Fallback or Default value, called when a real value is not available  
        internal object UseFallbackValue()
        {
            object value = FallbackValue;
 
            // if there's a problem with the fallback, use Default instead
            if (value == DefaultValueObject) 
            { 
                value = DependencyProperty.UnsetValue;
            } 

            if (value != DependencyProperty.UnsetValue)
            {
                UsingFallbackValue = true; 
            }
            else 
            { 
                // if fallback isn't available, use Default (except when in a binding collection)
                if (Status == BindingStatus.Active) 
                    SetStatus(BindingStatus.UpdateTargetError);

                if (!IsInBindingExpressionCollection)
                { 
                    value = DefaultValue;
 
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Information, TraceData.NoValueToTransfer, this); 
                    }
                }
            }
 
            return value;
        } 
 
        // determine if the given value is "null" (in a general sense)
        internal bool IsNullValue(object value) 
        {
            if (value == null)
                return true;
 
            if (Convert.IsDBNull(value))
                return true; 
 
            if (IsSqlNull(value))
                return true; 

            return false;
        }
 
        // return true if the value is null in the SqlTypes sense
        bool IsSqlNull(object value) 
        { 
            Type type = value.GetType();
            return Engine.IsINullable(type) && IsSqlNullImpl(value); 
        }

        // separate function to avoid loading System.Data unnecessarily
        [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
        static bool IsSqlNullImpl(object value)
        { 
            System.Data.SqlTypes.INullable nullable = value as System.Data.SqlTypes.INullable; 
            return (nullable != null && nullable.IsNull);
        } 

        // determine a "null" value appropriate for the given type
        internal object NullValueForType(Type type)
        { 
            if (type == null)
                return null; 
 
            object sqlNull;
            if (IsSqlNullableType(type, out sqlNull)) 
                return sqlNull;

            if (!type.IsValueType)
                return null; 

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
                return null; 

            return DependencyProperty.UnsetValue; 
        }

        // return true if the type is nullable in the SqlTypes sense.  If so, return the null value.
        bool IsSqlNullableType(Type type, out object nullValue) 
        {
            if (Engine.IsINullable(type)) 
            { 
                return IsSqlNullableTypeImpl(type, out nullValue);
            } 
            else
            {
                nullValue = null;
                return false; 
            }
        } 
 
        // separate function to avoid loading System.Data unnecessarily
        [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
        static bool IsSqlNullableTypeImpl(Type type, out object nullValue)
        {
            // some SqlTypes are classes with a Null property.  Others are structs with a Null field.  Try both.
            System.Reflection.FieldInfo nullField = type.GetField("Null", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy); 
            if (nullField != null)
            { 
                nullValue = nullField.GetValue(null); 
                return true;
            } 

            System.Reflection.PropertyInfo nullProperty = type.GetProperty("Null", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy);
            if (nullProperty != null)
            { 
                nullValue = nullProperty.GetValue(null, null);
                return true; 
            } 

            nullValue = null; 
            return false;
        }

        internal ValidationRule LookupValidationRule(Type type) 
        {
            ValidationRule result = ParentBindingBase.GetValidationRule(type); 
 
            if (result == null && _parentBindingExpression != null)
            { 
                result = _parentBindingExpression.LookupValidationRule(type);
            }

            return result; 
        }
 
        // discover the binding group (if any) that this binding should join, 
        // and join it.  More precisely, cause the root binding to join.
        internal void JoinBindingGroup(bool isReflective, DependencyObject contextElement) 
        {
            BindingGroup bindingGroup = RootBindingExpression.FindBindingGroup(isReflective, contextElement);

            if (bindingGroup != null) 
            {
                JoinBindingGroup(bindingGroup, /*explicit*/false); 
            } 
        }
 
        // remove the binding from its group
        internal void LeaveBindingGroup()
        {
            BindingExpressionBase root = RootBindingExpression; 
            BindingGroup bg = root.BindingGroup;
            if (bg != null) 
            { 
                bg.BindingExpressions.Remove(root);
                root._bindingGroup = null; 
            }
        }

        // discover the binding group (if any) that this root binding should join. 
        BindingGroup FindBindingGroup(bool isReflective, DependencyObject contextElement)
        { 
            Debug.Assert(RootBindingExpression == this, "Only call this with a root binding"); 

            // if we've already joined (or failed to join) a group, just return the result 
            if (_bindingGroup != null)
            {
                return (BindingGroup)_bindingGroup.Target;
            } 

            BindingGroup bg; 
            string groupName = ParentBindingBase.BindingGroupName; 

            // a null group name means "don't join any group". 
            if (groupName == null)
            {
                MarkAsNonGrouped();
                return null; 
            }
 
            // an empty group name means join by DataContext 
            if (String.IsNullOrEmpty(groupName))
            { 
                // check further preconditions:
                if (!isReflective ||                // must have target-to-source data flow
                    contextElement == null)         // must use data context
                { 
                    // later child bindings might pass this test, so don't mark
                    // this root binding as non-grouped yet 
                    return null; 
                }
 
                // only the innermost binding group is eligible
                bg = (BindingGroup)contextElement.GetValue(FrameworkElement.BindingGroupProperty);
                if (bg == null)
                { 
                    MarkAsNonGrouped();
                    return null; 
                } 

                // the context element must share data context with the group 
                DependencyProperty dataContextDP = FrameworkElement.DataContextProperty;
                DependencyObject groupContextElement = bg.InheritanceContext;
                if (groupContextElement == null ||
                    !Object.Equals( contextElement.GetValue(dataContextDP), 
                                    groupContextElement.GetValue(dataContextDP)))
                { 
                    MarkAsNonGrouped(); 
                    return null;
                } 

                // if the binding survives the gauntlet, return the group
                return bg;
            } 

            // a non-empty group name means join by name 
            else 
            {
                // walk up the tree, looking for a matching binding group 
                DependencyProperty bindingGroupDP = FrameworkElement.BindingGroupProperty;
                FrameworkObject fo = new FrameworkObject(TargetElement);
                while (fo.DO != null)
                { 
                    BindingGroup bgCandidate = (BindingGroup)fo.DO.GetValue(bindingGroupDP);
                    if (bgCandidate == null) 
                    { 
                        MarkAsNonGrouped();
                        return null; 
                    }

                    if (bgCandidate.Name == groupName)
                    { 
                        // return the matching group
                        return bgCandidate; 
                    } 

                    fo = fo.FrameworkParent; 
                }

                // no match - report an error
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error, 
                            TraceData.BindingGroupNameMatchFailed(groupName), 
                            this);
                } 

                MarkAsNonGrouped();
                return null;
            } 
        }
 
        // add a binding to the given binding group 
        internal void JoinBindingGroup(BindingGroup bg, bool explicitJoin)
        { 
            BindingExpressionBase root = null;  // set to non-null by the next loop

            for (   BindingExpressionBase bindingExpr = this;
                    bindingExpr != null; 
                    bindingExpr = bindingExpr.ParentBindingExpressionBase)
            { 
                root = bindingExpr; 

                // bindings in a group update Explicitly, unless declared otherwise 
                bindingExpr.OnBindingGroupChanged(/*joining*/true);

                bg.AddToValueTable(bindingExpr);
            } 

            // add the root binding to the group 
            if (root._bindingGroup == null) 
            {
                // use WeakReference because the BindingGroup contains a strong reference 
                // to the visual tree (via InheritanceContext)
                root._bindingGroup = new WeakReference(bg);

                // when the group is implicitly discovered, always add the root binding to the group's collection. 
                // When the binding is added explicitly - via BindingGroup.BindingExpressions.Add() -
                // check first to see if it has already been added 
                bool addToGroup = explicitJoin ? !bg.BindingExpressions.Contains(root) : true; 
                if (addToGroup)
                { 
                    bg.BindingExpressions.Add(root);
                }

                // in the explicit case, register its items and values with the binding group 
                // (the implicit case does this when the bindings activate)
                if (explicitJoin) 
                { 
                    root.UpdateBindingGroup(bg);
                } 
            }
            else
            {
                if (root.BindingGroup != bg) 
                    throw new InvalidOperationException(SR.Get(SRID.BindingGroup_CannotChangeGroups));
            } 
        } 

        // mark a binding as non-grouped, so that we avoid doing the discovery again 
        void MarkAsNonGrouped()
        {
            // Leaf bindings only get asked once, so there's no need to add a mark
            if (!(this is BindingExpression)) 
            {
                _bindingGroup = new WeakReference(null); 
            } 
        }
 
        /// 
        /// Handle events from the centralized event table
        /// 
        internal virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        {
            return false;       // unrecognized event 
        } 

        private bool TestFlag(PrivateFlags flag) 
        {
            return (_flags & flag) != 0;
        }
 
        private void ChangeFlag(PrivateFlags flag, bool value)
        { 
            if (value)  _flags |=  flag; 
            else        _flags &= ~flag;
        } 

        //-----------------------------------------------------
        //
        //  Internal Properties 
        //
        //------------------------------------------------------ 
 
        internal DependencyProperty TargetProperty { get { return _targetProperty; } }
 
        // A BindingExpression cannot hold a strong reference to the target element - this
        // leads to memory leaks (bug 871139).  The problem is that BindingExpression and its workers
        // register for events from the data item, creating a reference from
        // the data item to the BindingExpression.  The data item typically has a long lifetime, 
        // so if the BindingExpression held a SR to the target, the target element would
        // also stay alive forever. 
        //      Instead, BindingExpression holds a WeakReference to the target.  This means we 
        // have to check it before dereferencing (here), and cope when the
        // reference fails (in callers to this property).  Requests for the TargetElement 
        // are not trivial, so callers should request it once and cache the result
        // in a local variable.  They should not save it in a global or instance
        // variable of course;  that would defeat the purpose of the WR.
        //      This allows the target element to be GC'd when it's no longer in 
        // use by the tree or application.  The next time the BindingExpression asks for
        // its TargetElement, the WR will fail.  At this point, the BindingExpression is no 
        // longer useful, so it can sever all connections to the outside world (i.e. 
        // stop listening for events).  This allows the BindingExpression itself to be GC'd.
        internal DependencyObject TargetElement 
        {
            get
            {
                if (_targetElement != null) 
                {
                    DependencyObject result = _targetElement.Target as DependencyObject; 
                    if (result != null) 
                        return result;
 
                    // target has been GC'd, sever all connections
                    _targetElement = null;      // prevents re-entry from Detach()
                    Detach();
                } 

                return null; 
            } 
        }
 
        internal WeakReference TargetElementReference
        {
            get { return _targetElement; }
        } 

        internal DataBindEngine Engine 
        { 
            get { return _engine; }
        } 

        internal Dispatcher Dispatcher
        {
            get { return (_engine != null) ? _engine.Dispatcher : null; } 
        }
 
        internal object Value 
        {
            get 
            {
                if (_value == DefaultValueObject)
                {
                    // don't notify listeners.  This isn't a real value change. 
                    ChangeValue(UseFallbackValue(), false /*notify*/);
                } 
                return _value; 
            }
            set 
            {
                ChangeValue(value, true);
                Dirty();
            } 
        }
 
        internal WeakDependencySource[] WeakSources 
        {
            get { return _sources; } 
        }

        /// 
        ///     NoTarget DependencyProperty, a placeholder used by BindingExpressions with no target property 
        /// 
        internal static readonly DependencyProperty NoTargetProperty = 
                DependencyProperty.RegisterAttached("NoTarget", typeof(object), typeof(BindingExpressionBase), 
                                            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));
 
        internal TraceLog TraceLog { get { return _traceLog; } }

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

        ///  
        /// Attach the binding expression to the given target object and property.
        /// 
        internal void Attach(DependencyObject target, DependencyProperty dp)
        { 
            // make sure we're on the right thread to access the target
            if (target != null) 
            { 
                target.VerifyAccess();
            } 

            IsAttaching = true;
            AttachOverride(target, dp);
            IsAttaching = false; 
        }
 
        ///  
        /// Detach the binding expression from its target object and property.
        ///  
        internal void Detach()
        {
            if (_status == BindingStatus.Detached || IsDetaching)
                return; 

            IsDetaching = true; 
            DetachOverride(); 
            IsDetaching = false;
        } 

        internal void SetStatus(BindingStatus status)
        {
            if (_status == BindingStatus.Detached && status != _status) 
            {
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionStatusChanged, _status, status)); 
            } 

            _status = status; 

            if (_traceLog != null)
            {
                _traceLog.Add("Set status = {0} {1}", _status, new StackTrace()); 
            }
        } 
 
        // convert a user-supplied fallback value to a usable equivalent
        //  returns:    UnsetValue          if user did not supply a fallback value 
        //              value               if fallback value is legal
        //              DefaultValueObject  otherwise
        internal static object ConvertFallbackValue(object value, DependencyProperty dp, object sender)
        { 
            Exception e;
            object result = ConvertValue(value, dp, out e); 
 
            if (result == DefaultValueObject)
            { 
                if (TraceData.IsEnabled)
                {
                    TraceData.Trace(TraceEventType.Error,
                            TraceData.FallbackConversionFailed( 
                                AvTrace.ToStringHelper(value),
                                AvTrace.TypeName(value), 
                                dp.Name, 
                                dp.PropertyType.Name),
                            sender, e); 
                }
            }

            return result; 
        }
 
        // convert a user-supplied TargetNullValue to a usable equivalent 
        //  returns:    UnsetValue          if user did not supply a fallback value
        //              value               if fallback value is legal 
        //              DefaultValueObject  otherwise
        internal static object ConvertTargetNullValue(object value, DependencyProperty dp, object sender)
        {
            Exception e; 
            object result = ConvertValue(value, dp, out e);
 
            if (result == DefaultValueObject) 
            {
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error,
                            TraceData.TargetNullValueConversionFailed(
                                AvTrace.ToStringHelper(value), 
                                AvTrace.TypeName(value),
                                dp.Name, 
                                dp.PropertyType.Name), 
                            sender, e);
                } 
            }

            return result;
        } 

        static object ConvertValue(object value, DependencyProperty dp, out Exception e) 
        { 
            object result;
            e = null; 

            if (value == DependencyProperty.UnsetValue || dp.IsValidValue(value))
            {
                result = value; 
            }
            else 
            { 
                result = null;  // placeholder to keep compiler happy
                // if value isn't the right type, use a type converter to get a better value 
                bool success = false;
                TypeConverter converter = DefaultValueConverter.GetConverter(dp.PropertyType);
                if (converter != null && converter.CanConvertFrom(value.GetType()))
                { 
                    // 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 
                    {
                        result = converter.ConvertFrom(null, CultureInfo.InvariantCulture, value); 
                        success = dp.IsValidValue(result); 
                    }
 
                    // Catch all exceptions.  If we can't convert the fallback value, it doesn't
                    // matter why not;  we should always use the default value instead.
                    // (See bug 1853628 for an example of a converter that throws
                    // an exception not mentioned in the documentation for ConvertFrom.) 
                    catch (Exception ex)
                    { 
                        e = ex; 
                    }
                    catch // non CLS compliant exception 
                    {
                    }

                    #pragma warning restore 56500 
                    #pragma warning restore 1634, 1691
                } 
 
                if (!success)
                { 
                    // if can't convert it, don't use it
                    result = DefaultValueObject;
                }
            } 

            return result; 
        } 

        // Certain trace reports should be marked as 'error' unless the binding 
        // is prepared to handle it in some way (e.g. FallbackValue), in which
        // case 'warning'.
        internal TraceEventType TraceLevel
        { 
            get
            { 
                // FallbackValue is present 
                if (ParentBindingBase.FallbackValue != DependencyProperty.UnsetValue)
                    return TraceEventType.Warning; 

                // Binding is a member of MultiBinding or PriorityBinding
                if (IsInBindingExpressionCollection)
                    return TraceEventType.Warning; 

                // all other cases - error 
                return TraceEventType.Error; 
            }
        } 

        internal virtual void Activate()
        {
        } 

        internal virtual void Deactivate() 
        { 
        }
 
        internal virtual void Update(bool synchronous)
        {
        }
 
        internal void UpdateValidationError(ValidationError validationError)
        { 
            if (_validationError != null) 
            {
                ValidationError oldValidationError = _validationError; 
                _validationError = null;    // clear before raising events, so that HasError is correct
                RemoveValidationError(oldValidationError);
            }
 
            _validationError = validationError;
 
            if (_validationError != null) 
            {
                AddValidationError(_validationError); 
            }
        }

        internal void AddValidationError(ValidationError validationError) 
        {
            // add the error to the target element 
            Validation.AddValidationError(validationError, TargetElement, NotifyOnValidationError); 

            // add the error to the binding group's target element 
            BindingGroup bindingGroup = BindingGroup;
            if (bindingGroup != null)
            {
                bindingGroup.AddValidationError(validationError); 
            }
        } 
 
        internal void RemoveValidationError(ValidationError validationError)
        { 
            // remove the error from the target element
            Validation.RemoveValidationError(validationError, TargetElement, NotifyOnValidationError);

            // remove the error from the binding group's target element 
            BindingGroup bindingGroup = BindingGroup;
            if (bindingGroup != null) 
            { 
                bindingGroup.RemoveValidationError(validationError);
            } 
        }

        // remove all errors raised at the given step, in preparation for running
        // the rules at that step 
        internal void ClearValidationErrors(ValidationStep validationStep)
        { 
            if (_validationError == null || _validationError.RuleInError.ValidationStep != validationStep) 
                return;
 
            RemoveValidationError(_validationError);
            _validationError = null;
        }
 
        internal void ChangeSources(WeakDependencySource[] newSources)
        { 
            if (IsInBindingExpressionCollection) 
                ParentBindingExpressionBase.ChangeSourcesForChild(this, newSources);
            else 
                ChangeSources(TargetElement, TargetProperty, newSources);

            // store the sources with weak refs, so they don't cause memory leaks (bug 980041)
            _sources = newSources; 
        }
 
        ///  
        /// combine the sources of BindingExpressions, using new sources for
        /// the BindingExpression at the given index 
        /// 
        /// -1 to indicate no new sources
        /// collection of child binding expressions 
        /// how many child expressions to include 
        /// use null when no new sources
        ///  
        internal static WeakDependencySource[] CombineSources(int index, Collection bindingExpressions, int count, WeakDependencySource[] newSources) 
        {
            if (index == count) 
            {
                // Be sure to include newSources if they are being appended
                count++;
            } 

            Collection tempList = new Collection(); 
 
            for (int i = 0; i < count; ++i)
            { 
                BindingExpressionBase bindExpr = bindingExpressions[i];
                WeakDependencySource[] sources = (i==index) ? newSources :
                                            (bindExpr != null) ? bindExpr.WeakSources :
                                            null; 
                int m = (sources == null) ? 0 : sources.Length;
                for (int j = 0; j < m; ++j) 
                { 
                    WeakDependencySource candidate = sources[j];
 
                    // don't add duplicate source
                    for (int k = 0; k < tempList.Count; ++k)
                    {
                        WeakDependencySource prior = tempList[k]; 
                        if (candidate.DependencyObject == prior.DependencyObject &&
                            candidate.DependencyProperty == prior.DependencyProperty) 
                        { 
                            candidate = null;
                            break; 
                        }
                    }

                    if (candidate != null) 
                        tempList.Add(candidate);
                } 
            } 

            WeakDependencySource[] result; 
            if (tempList.Count > 0)
            {
                result = new WeakDependencySource[tempList.Count];
                tempList.CopyTo(result, 0); 
                tempList.Clear();
            } 
            else 
            {
                result = null; 
            }

            return result;
        } 

        internal void ResolvePropertyDefaultSettings(BindingMode mode, UpdateSourceTrigger updateTrigger, FrameworkPropertyMetadata fwMetaData) 
        { 
            // resolve "property-default" dataflow
            if (mode == BindingMode.Default) 
            {
                BindingFlags f = BindingFlags.OneWay;
                if (fwMetaData != null && fwMetaData.BindsTwoWayByDefault)
                { 
                    f = BindingFlags.TwoWay;
                } 
 
                ChangeFlag(PrivateFlags.iPropagationMask, false);
                ChangeFlag((PrivateFlags)f, true); 

                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ResolveDefaults))
                {
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.ResolveDefaultMode(
                                            TraceData.Identify(this), 
                                            (f == BindingFlags.OneWay) ? BindingMode.OneWay : BindingMode.TwoWay)); 
                }
            } 

            Debug.Assert((_flags & PrivateFlags.iPropagationMask) != PrivateFlags.iPropDefault,
                "BindingExpression should not have Default propagation");
 
            // resolve "property-default" update trigger
            if (updateTrigger == UpdateSourceTrigger.Default) 
            { 
                UpdateSourceTrigger ust = GetDefaultUpdateSourceTrigger(fwMetaData);
 
                SetUpdateSourceTrigger(ust);

                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ResolveDefaults))
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.ResolveDefaultUpdate( 
                                            TraceData.Identify(this), 
                                            ust));
                } 
            }

            Invariant.Assert((_flags & PrivateFlags.iUpdateMask) != PrivateFlags.iUpdateDefault,
                "BindingExpression should not have Default update trigger"); 
        }
 
        // return the effective update trigger, used when binding doesn't set one explicitly 
        internal UpdateSourceTrigger GetDefaultUpdateSourceTrigger(FrameworkPropertyMetadata fwMetaData)
        { 
            UpdateSourceTrigger ust =
                IsInMultiBindingExpression ? UpdateSourceTrigger.Explicit :
                (fwMetaData != null) ? fwMetaData.DefaultUpdateSourceTrigger :
                                    UpdateSourceTrigger.PropertyChanged; 
            return ust;
        } 
 
        internal void SetUpdateSourceTrigger(UpdateSourceTrigger ust)
        { 
            ChangeFlag(PrivateFlags.iUpdateMask, false);
            ChangeFlag((PrivateFlags)BindingBase.FlagsFrom(ust), true);
        }
 
        internal void DetermineEffectiveStringFormat()
        { 
            Type targetType = TargetProperty.PropertyType; 
            if (targetType != typeof(String))
            { 
                // if the target type isn't String, we don't need a string format
                return; // _effectiveStringFormat is already null
            }
 
            // determine the effective target type and the declared string format
            // by looking up the tree of binding expressions 
            string stringFormat = ParentBindingBase.StringFormat; 
            BindingExpressionBase be = this.ParentBindingExpressionBase;
 
            while (be != null)
            {
                if (be is MultiBindingExpression)
                { 
                    // MultiBindings should receive object values, not string
                    targetType = typeof(Object); 
                    break; 
                }
                else if (stringFormat == null && be is PriorityBindingExpression) 
                {
                    // use a PriorityBinding's string format, unless we already
                    // have a more specific one
                    stringFormat = be.ParentBindingBase.StringFormat; 
                }
 
                be = be.ParentBindingExpressionBase; 
            }
 
            // if we need a string format, cache it
            if (targetType == typeof(String))
            {
                #if NotToday 
                // special case: when these conditions all apply
                //      a) target element belongs to a DataTemplate 
                //      b) template was found by implicit (type-based) lookup 
                //      c) container (ContentPresenter) has a string format
                //      d) binding has no effective string format 
                // then use the CP's string format.  This enables scenarios like
                //      
                //           
                //      
                // where you'd like to control the format at the point of use, 
                // rather than at the point of template declaration.  This is 
                // especially useful when the template is declared in a global place
                // like app resources or a theme file.  In particular it makes the 
                // GroupStyle.HeaderStringFormat property work;  the template for
                // GroupItem is defined in the theme, but needs to pick up formatting
                // from the app's markup.
 
                if (stringFormat == null)   // (d)
                { 
                    FrameworkObject fo = new FrameworkObject(TargetElement); 
                    ContentPresenter cp = fo.TemplatedParent as ContentPresenter;
                    if (cp != null &&                       // (a) 
                        cp.ContentStringFormat != null)     // (c)
                    {
                        DataTemplate dt = cp.TemplateInternal as DataTemplate;
                        if (dt != null &&                   // (a) 
                            dt.DataType != null)            // (b)
                        { 
                            stringFormat = cp.ContentStringFormat; 
                        }
                    } 
                }
                #endif

                if (!String.IsNullOrEmpty(stringFormat)) 
                {
                    _effectiveStringFormat = Helper.GetEffectiveStringFormat(stringFormat); 
                } 
            }
        } 

        internal void DetermineEffectiveTargetNullValue()
        {
            Type targetType = TargetProperty.PropertyType; 

            // determine the effective target type and the declared TargetNullValue 
            // by looking up the tree of binding expressions 
            object targetNullValue = ParentBindingBase.TargetNullValue;
            BindingExpressionBase be = this.ParentBindingExpressionBase; 

            while (be != null)
            {
                if (be is MultiBindingExpression) 
                {
                    // MultiBindings should receive object values 
                    targetType = typeof(Object); 
                    break;
                } 
                else if (targetNullValue == DependencyProperty.UnsetValue && be is PriorityBindingExpression)
                {
                    // use a PriorityBinding's TargetNullValue, unless we already
                    // have a more specific one 
                    targetNullValue = be.ParentBindingBase.TargetNullValue;
                } 
 
                be = be.ParentBindingExpressionBase;
            } 

            // if user declared a TargetNullValue, make sure it has the right type.
            if (targetNullValue != DependencyProperty.UnsetValue)
            { 
                targetNullValue = ConvertTargetNullValue(targetNullValue, TargetProperty, this);
                if (targetNullValue == DefaultValueObject) 
                { 
                    // if not, ignore it (having logged a trace message)
                    targetNullValue = DependencyProperty.UnsetValue; 
                }
            }

            // for back-compat, don't turn on TargetNullValue unless user explicitly 
            // asks for it.  This means users have to add TargetNullValue to get
            // pretty basic scenarios to work (e.g. binding a TextBox to a database 
            // string field that supports DBNull).  It's painful, but can't be 
            // helped.
            #if TargetNullValueBC //BreakingChange 
            // if no declared (or poorly declared) value, make one up
            if (targetNullValue == DependencyProperty.UnsetValue)
            {
                targetNullValue = NullValueForType(targetType); 
            }
            #endif 
 
            _effectiveTargetNullValue = targetNullValue;
        } 

        // To prevent memory leaks, we store WeakReferences to certain objects
        // in various places:  _dataItem, _sources, worker fields.  The logic
        // for this is centralized in these two static methods.  (See bug 940041) 

        internal static object CreateReference(object item) 
        { 
            // One source of leaks is the reference cycle formed when a BindingExpression's
            // source item contains a reference chain to the target element: 
            //      target -> BindingExpression -> source item -> target
            //
            // Making the second link into a WeakReference incurs some cost,
            // so it should be avoided if we know the third link never exists. 
            // We definitely can't avoid this when the item is a DependencyObject,
            // since it's reasonably common for the third link to occur (e.g. 
            // a ContextMenu contains a link to its Popup, which has a property 
            // bound back to the ContextMenu).
            // 
            // For safety, we choose to use WeakRef all the time, unless the item is null.
            // Exception (bug 1124954):  Keep a strong reference to
            // BindingListCollectionView - this keeps the underlying DataView
            // alive, when nobody else will. 
            // Exception (bug 1970505):  Don't allocate a WeakRef for the common
            // case of the NullDataItem 
 
            if (item != null &&
                !(item is BindingListCollectionView) && 
                !(item == BindingExpression.NullDataItem))
            {
                item = new WeakReference(item);
            } 

#if USE_ITEM_REFERENCE 
            item = new ItemReference(item); 
#endif
 
            return item;
        }

        // like CreateReference, but use an existing WeakReference 
        internal static object CreateReference(WeakReference item)
        { 
            object result = item; 
#if USE_ITEM_REFERENCE
            result = new ItemReference(item); 
#endif
            return result;
        }
 
        // like CreateReference, except re-target the old WeakReference (if any)
        internal static object ReplaceReference(object oldReference, object item) 
        { 
            if (item != null &&
                !(item is BindingListCollectionView) && 
                !(item == BindingExpression.NullDataItem))
            {
#if USE_ITEM_REFERENCE
                // if this cast fails, it's because you have done a direct assignment of an 
                // item to some field instead of assigning the result of CreateReference.
                oldReference = ((ItemReference)oldReference).Item; 
#endif 
                WeakReference wr = oldReference as WeakReference;
                if (wr != null) 
                {
                    wr.Target = item;
                    item = wr;
                } 
                else
                { 
                    item = new WeakReference(item); 
                }
            } 

#if USE_ITEM_REFERENCE
            item = new ItemReference(item);
#endif 

            return item; 
        } 

        internal static object GetReference(object reference) 
        {
            if (reference == null)
                return null;
 
#if USE_ITEM_REFERENCE
            // if this cast fails, it's because you have done a direct assignment of an 
            // item to some field instead of assigning the result of CreateReference. 
            reference = ((ItemReference)reference).Item;
#endif 

            WeakReference wr = reference as WeakReference;
            if (wr != null)
                return wr.Target; 
            else
                return reference; 
        } 

        internal static void InitializeTracing(BindingExpressionBase expr, DependencyObject d, DependencyProperty dp) 
        {
            BindingBase parent = expr.ParentBindingBase;
        }
 
        //------------------------------------------------------
        // 
        //  Private Methods 
        //
        //----------------------------------------------------- 

#if USE_ITEM_REFERENCE

        private class ItemReference 
        {
            internal ItemReference(object item) 
            { 
                _item = item;
            } 

            internal object Item { get { return _item; } }

            object _item; 
        }
 
#endif 

        // change WeakDependencySources to (strong) DependencySources, and notify 
        // the property engine about the new sources
        void ChangeSources(DependencyObject target, DependencyProperty dp, WeakDependencySource[] newSources)
        {
            DependencySource[] sources; 

            if (newSources != null) 
            { 
                // convert weak reference to strong
                sources = new DependencySource[newSources.Length]; 
                int n = 0;
                for (int i = 0; i < newSources.Length; ++i)
                {
                    DependencyObject sourceDO = newSources[i].DependencyObject; 
                    if (sourceDO != null)
                    { 
                        // only include sources that are still alive 
                        sources[n++] = new DependencySource(sourceDO, newSources[i].DependencyProperty);
                    } 
                }

                // if any of the sources were no longer alive, trim the array
                if (n < newSources.Length) 
                {
                    DependencySource[] temp; 
                    if (n > 0) 
                    {
                        temp = new DependencySource[n]; 
                        Array.Copy(sources, 0, temp, 0, n);
                    }
                    else
                    { 
                        temp = null;
                    } 
 
                    sources = temp;
                } 
            }
            else
            {
                sources = null; 
            }
 
            // notify property engine 
            ChangeSources(target, dp, sources);
        } 

        // this method is here just to avoid the compiler error
        // error CS0649: Warning as Error: Field 'System.Windows.Data.BindingExpression._traceLog' is never assigned to, and will always have its default value null
        void InitializeTraceLog() 
        {
            _traceLog = new TraceLog(20); 
        } 

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

        BindingBase         _binding; 
        WeakReference       _targetElement; 
        DependencyProperty  _targetProperty;
        DataBindEngine      _engine; 
        PrivateFlags        _flags;
        BindingExpressionBase _parentBindingExpression;
        object              _value = DefaultValueObject;
        BindingStatus       _status; 
        TraceLog            _traceLog;
        ValidationError     _validationError; 
        WeakDependencySource[]  _sources; 
        string              _effectiveStringFormat;
        object              _effectiveTargetNullValue; 
        WeakReference       _bindingGroup;

        object                  _culture = DefaultValueObject;
 
        ///  Sentinel meaning "field has its default value" 
        internal static readonly object DefaultValueObject = new object(); 
    } 

} 


// 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 BindingExpressionBase object, 
//              base class for BindingExpression, PriorityBindingExpression, 
//              and MultiBindingExpression.
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
 
// build with this symbol defined to catch errors about not using
// BindingExpression.GetReference correctly 
//#define USE_ITEM_REFERENCE 

using System; 
using System.Collections.ObjectModel;   // Collection
using System.ComponentModel;        // TypeConverter
using System.Diagnostics;           // StackTrace
using System.Globalization;         // CultureInfo 

using System.Windows;               // FrameworkElement 
using System.Windows.Controls;      // Validation 
using System.Windows.Markup;        // XmlLanguage
using System.Windows.Threading;     // Dispatcher 
using MS.Internal;                  // Invariant.Assert
using MS.Internal.Controls;         // ValidationErrorCollection
using MS.Internal.Data;             // DataBindEngine
using MS.Internal.KnownBoxes;       // BooleanBoxes 
using MS.Internal.Utility;          // TraceLog
 
namespace System.Windows.Data 
{
 
    /// 
    /// Base class for Binding Expressions.
    /// 
    public abstract class BindingExpressionBase : Expression, IWeakEventListener 
    {
 
        // Flags indicating run-time properties of a BindingExpression 
        [Flags]
        internal enum BindingFlags 
        {
            // names used by Binding

            OneWay                  = PrivateFlags.iSourceToTarget, 
            TwoWay                  = PrivateFlags.iSourceToTarget | PrivateFlags.iTargetToSource,
            OneWayToSource          = PrivateFlags.iTargetToSource, 
            OneTime                 = 0, 
            PropDefault             = PrivateFlags.iPropDefault,
            NotifyOnTargetUpdated   = PrivateFlags.iNotifyOnTargetUpdated, 
            NotifyOnSourceUpdated   = PrivateFlags.iNotifyOnSourceUpdated,
            NotifyOnValidationError = PrivateFlags.iNotifyOnValidationError,
            UpdateOnPropertyChanged = 0,
            UpdateOnLostFocus       = PrivateFlags.iUpdateOnLostFocus, 
            UpdateExplicitly        = PrivateFlags.iUpdateExplicitly,
            UpdateDefault           = PrivateFlags.iUpdateDefault, 
            PathGeneratedInternally = PrivateFlags.iPathGeneratedInternally, 
            ValidatesOnExceptions   = PrivateFlags.iValidatesOnExceptions,
            ValidatesOnDataErrors   = PrivateFlags.iValidatesOnDataErrors, 

            Default                 = PropDefault | UpdateDefault,

            ///  Error value, returned by FlagsFrom to indicate faulty input 
            IllegalInput                = PrivateFlags.iIllegalInput,
 
            PropagationMask = OneWay | TwoWay | OneWayToSource | OneTime | PropDefault, 
            UpdateMask      = UpdateOnPropertyChanged | UpdateOnLostFocus | UpdateExplicitly | UpdateDefault,
        } 

        [Flags]
        private enum PrivateFlags
        { 
            // internal use
 
            iSourceToTarget             = 0x00000001, 
            iTargetToSource             = 0x00000002,
            iPropDefault                = 0x00000004, 
            iNotifyOnTargetUpdated      = 0x00000008,
            iDefaultValueConverter      = 0x00000010,
            iInTransfer                 = 0x00000020,
            iInUpdate                   = 0x00000040, 
            iTransferPending            = 0x00000080,
            iNeedDataTransfer           = 0x00000100, 
            iTransferDeferred           = 0x00000200,   // used by MultiBindingExpression 
            iUpdateOnLostFocus          = 0x00000400,
            iUpdateExplicitly           = 0x00000800, 
            iUpdateDefault              = iUpdateExplicitly | iUpdateOnLostFocus,
            iNeedUpdate                 = 0x00001000,
            iPathGeneratedInternally    = 0x00002000,
            iUsingMentor                = 0x00004000, 
            iResolveNamesInTemplate     = 0x00008000,
            iDetaching                  = 0x00010000, 
            iNeedsCollectionView        = 0x00020000, 
            iInPriorityBindingExpression= 0x00040000,
            iInMultiBindingExpression   = 0x00080000, 
            iUsingFallbackValue         = 0x00100000,
            iNotifyOnValidationError    = 0x00200000,
            iAttaching                  = 0x00400000,
            iNotifyOnSourceUpdated      = 0x00800000, 
            iValidatesOnExceptions      = 0x01000000,
            iValidatesOnDataErrors      = 0x02000000, 
            iIllegalInput               = 0x04000000, 
            iNeedsValidation            = 0x08000000,
 
            iPropagationMask = iSourceToTarget | iTargetToSource | iPropDefault,
            iUpdateMask      = iUpdateOnLostFocus | iUpdateExplicitly,
        }
 
        //-----------------------------------------------------
        // 
        //  Constructors 
        //
        //----------------------------------------------------- 

        ///  Constructor 
        internal BindingExpressionBase(BindingBase binding, BindingExpressionBase parent) : base(ExpressionMode.SupportsUnboundSources)
        { 
            if (binding == null)
                throw new ArgumentNullException("binding"); 
 
            _binding = binding;
            _parentBindingExpression = parent; 

            _flags = (PrivateFlags)binding.Flags;

            if (parent != null) 
            {
                ResolveNamesInTemplate = parent.ResolveNamesInTemplate; 
 
                Type type = parent.GetType();
                if (type == typeof(MultiBindingExpression)) 
                    ChangeFlag(PrivateFlags.iInMultiBindingExpression, true);
                else if (type == typeof(PriorityBindingExpression))
                    ChangeFlag(PrivateFlags.iInPriorityBindingExpression, true);
            } 

            // initialize tracing information 
            PresentationTraceLevel traceLevel = PresentationTraceSources.GetTraceLevel(binding); 

            if (traceLevel > 0) 
            {
                // copy TraceLevel from parent BindingBase - it can be changed later
                PresentationTraceSources.SetTraceLevel(this, traceLevel);
            } 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.CreateExpression)) 
            { 
                if (parent == null)
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.CreatedExpression(
                                            TraceData.Identify(this),
                                            TraceData.Identify(binding))); 
                }
                else 
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.CreatedExpressionInParent( 
                                            TraceData.Identify(this),
                                            TraceData.Identify(binding),
                                            TraceData.Identify(parent)));
                } 
            }
 
            if (LookupValidationRule(typeof(ExceptionValidationRule)) != null) 
            {
                ChangeFlag(PrivateFlags.iValidatesOnExceptions, true); 
            }

            if (LookupValidationRule(typeof(DataErrorValidationRule)) != null)
            { 
                ChangeFlag(PrivateFlags.iValidatesOnDataErrors, true);
            } 
        } 

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

        ///  Binding from which this expression was created  
        public BindingBase  ParentBindingBase  { get { return _binding; } } 

        /// Status of the BindingExpression 
        public BindingStatus Status { get { return _status; } }

        /// 
        ///     The ValidationError that caused this 
        ///     BindingExpression to be invalid.
        ///  
        public virtual ValidationError ValidationError 
        {
            get 
            {
                return _validationError;
            }
        } 

        ///  
        ///     HasError returns true if any of the ValidationRules 
        ///     in the ParentBinding failed its validation rule.
        ///  
        public virtual bool HasError
        {
            get
            { 
                return _validationError != null;
            } 
        } 

        //------------------------------------------------------ 
        //
        //  Public Methods
        //
        //------------------------------------------------------ 

        ///  Force a data transfer from source to target  
        public virtual void UpdateTarget() 
        {
        } 

        ///  Send the current value back to the source 
        ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource 
        public virtual void UpdateSource() 
        {
        } 
 
#region Expression overrides
 
        /// 
        ///     Notification that the Expression has been set as a property's value
        /// 
        ///  
        ///     Subclasses should not override OnAttach(), but must override Attach()
        ///  
        /// DependencyObject being set 
        /// Property being set
        internal sealed override void OnAttach(DependencyObject d, DependencyProperty dp) 
        {
            if (d == null)
                throw new ArgumentNullException("d");
            if (dp == null) 
                throw new ArgumentNullException("dp");
 
            Attach(d, dp); 
        }
 
        /// 
        ///     Notification that the Expression has been removed as a property's value
        /// 
        ///  
        ///     Subclasses should not override OnDetach(), but must override Detach()
        ///  
        /// DependencyObject being cleared 
        /// Property being cleared
        internal sealed override void OnDetach(DependencyObject d, DependencyProperty dp) 
        {
            Detach();
        }
 
        /// 
        ///     List of sources of the Expression 
        ///  
        /// Sources list
        internal override DependencySource[] GetSources() 
        {
            int j, k;
            int n = (_sources != null) ? _sources.Length : 0;
            if (n == 0) 
                return null;
 
            DependencySource[] result = new DependencySource[n]; 

            // convert the weak references into strong ones 
            for (j=0, k=0; k 
        /// Handle events from the centralized event table
        ///  
        bool IWeakEventListener.ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        {
            return ReceiveWeakEvent(managerType, sender, e); 
        }

#region BindingExpressions with no target DP
 
        //-----------------------------------------------------
        // 
        //  API for BindingExpressions with no target DP (task 20769) 
        //  This is internal for now, until we review whether we wish to
        //  make it public 
        //
        //------------------------------------------------------

        ///  Create an untargeted BindingExpression  
        internal static BindingExpressionBase CreateUntargetedBindingExpression(DependencyObject d, BindingBase binding)
        { 
            return binding.CreateBindingExpression(d, NoTargetProperty); 
        }
 
        ///  Attach the BindingExpression to its target element 
        /// 
        /// This method must be called once during the initialization.
        ///  
        /// The target element 
        internal void Attach(DependencyObject d) 
        { 
            Attach(d, NoTargetProperty);
        } 

        ///  This event is raised when the BindingExpression's value changes 
        internal event EventHandler ValueChanged;
 
        /* The following APIs are also needed for untargeted bindings, but they already exist
        for other reasons. 
 
        ///  The current value of the BindingExpression 
        internal object Value { get; set; } 

        ///  Activate the BindingExpression, using the given item as its root item. 
        internal void Activate(object item) {}
 
        ///  Deactivate the BindingExpression. 
        internal void Deactivate() {} 
 
        ///  Detach the BindingExpression from its target element 
        ///  
        /// This method must be called once when the BindingExpression is no longer needed.
        /// 
        internal void Detach() {}
 
        */
 
#endregion BindingExpressions with no target DP 

        //----------------------------------------------------- 
        //
        //  Protected Properties
        //
        //----------------------------------------------------- 

        ///  True if this binding expression is attaching  
        internal bool IsAttaching 
        {
            get { return TestFlag(PrivateFlags.iAttaching); } 
            set { ChangeFlag(PrivateFlags.iAttaching, value); }
        }

        ///  True if this binding expression is detaching  
        internal bool IsDetaching
        { 
            get { return TestFlag(PrivateFlags.iDetaching); } 
            set { ChangeFlag(PrivateFlags.iDetaching, value); }
        } 

        ///  True if this binding expression updates the target 
        internal bool IsDynamic
        { 
            get
            { 
                return (    TestFlag(PrivateFlags.iSourceToTarget) 
                        &&  (!IsInMultiBindingExpression || ParentMultiBindingExpression.IsDynamic));
            } 
        }

        ///  True if this binding expression updates the source 
        internal bool IsReflective 
        {
            get 
            { 
                return (    TestFlag(PrivateFlags.iTargetToSource)
                        &&  (!IsInMultiBindingExpression || ParentMultiBindingExpression.IsReflective)); 
            }
            set { ChangeFlag(PrivateFlags.iTargetToSource, value); }
        }
 
        ///  True if this binding expression uses a default ValueConverter 
        internal bool UseDefaultValueConverter 
        { 
            get { return TestFlag(PrivateFlags.iDefaultValueConverter); }
            set { ChangeFlag(PrivateFlags.iDefaultValueConverter, value); } 
        }

        ///  True if this binding expression is OneWayToSource 
        internal bool IsOneWayToSource 
        {
            get { return (_flags & PrivateFlags.iPropagationMask) == PrivateFlags.iTargetToSource; } 
        } 

        ///  True if this binding expression updates on PropertyChanged  
        internal bool IsUpdateOnPropertyChanged
        {
            get { return (_flags & PrivateFlags.iUpdateMask) == 0; }
        } 

        ///  True if this binding expression updates on LostFocus  
        internal bool IsUpdateOnLostFocus 
        {
            get { return TestFlag(PrivateFlags.iUpdateOnLostFocus); } 
        }

        ///  True if this binding expression has a pending target update 
        internal bool IsTransferPending 
        {
            get { return TestFlag(PrivateFlags.iTransferPending); } 
            set { ChangeFlag(PrivateFlags.iTransferPending, value); } 
        }
 
        ///  True if this binding expression is deferring a target update 
        internal bool TransferIsDeferred
        {
            get { return TestFlag(PrivateFlags.iTransferDeferred); } 
            set { ChangeFlag(PrivateFlags.iTransferDeferred, value); }
        } 
 
        ///  True if this binding expression is updating the target 
        internal bool IsInTransfer 
        {
            get { return TestFlag(PrivateFlags.iInTransfer); }
            set { ChangeFlag(PrivateFlags.iInTransfer, value); }
        } 

        ///  True if this binding expression is updating the source  
        internal bool IsInUpdate 
        {
            get { return TestFlag(PrivateFlags.iInUpdate); } 
            set { ChangeFlag(PrivateFlags.iInUpdate, value); }
        }

        ///  True if this binding expression is using the fallback value  
        internal bool UsingFallbackValue
        { 
            get { return TestFlag(PrivateFlags.iUsingFallbackValue); } 
            set { ChangeFlag(PrivateFlags.iUsingFallbackValue, value); }
        } 

        ///  True if this binding expression uses the mentor of the target element 
        internal bool UsingMentor
        { 
            get { return TestFlag(PrivateFlags.iUsingMentor); }
            set { ChangeFlag(PrivateFlags.iUsingMentor, value); } 
        } 

        ///  True if this binding expression should resolve ElementName within the template of the target element  
        internal bool ResolveNamesInTemplate
        {
            get { return TestFlag(PrivateFlags.iResolveNamesInTemplate); }
            set { ChangeFlag(PrivateFlags.iResolveNamesInTemplate, value); } 
        }
 
        ///  True if this binding expression has a pending target update  
        internal bool NeedsDataTransfer
        { 
            get { return TestFlag(PrivateFlags.iNeedDataTransfer); }
            set { ChangeFlag(PrivateFlags.iNeedDataTransfer, value); }
        }
 
        ///  True if this binding expression has a pending source update 
        internal bool NeedsUpdate 
        { 
            get { return TestFlag(PrivateFlags.iNeedUpdate); }
            set 
            {
                ChangeFlag(PrivateFlags.iNeedUpdate, value);
                if (value)
                { 
                    NeedsValidation = true;
                } 
            } 
        }
 
        ///  True if this binding expression needs validation 
        internal bool NeedsValidation
        {
            get { return TestFlag(PrivateFlags.iNeedsValidation); } 
            set { ChangeFlag(PrivateFlags.iNeedsValidation, value); }
        } 
 
        ///  True if this binding expression should raise the TargetUpdated event 
        internal bool NotifyOnTargetUpdated 
        {
            get { return TestFlag(PrivateFlags.iNotifyOnTargetUpdated); }
            set { ChangeFlag(PrivateFlags.iNotifyOnTargetUpdated, value); }
        } 

        ///  True if this binding expression should raise the SourceUpdated event  
        internal bool NotifyOnSourceUpdated 
        {
            get { return TestFlag(PrivateFlags.iNotifyOnSourceUpdated); } 
            set { ChangeFlag(PrivateFlags.iNotifyOnSourceUpdated, value); }
        }

        ///  True if this binding expression should raise the ValidationError event  
        internal bool NotifyOnValidationError
        { 
            get { return TestFlag(PrivateFlags.iNotifyOnValidationError); } 
            set { ChangeFlag(PrivateFlags.iNotifyOnValidationError, value); }
        } 

        ///  True if this binding expression belongs to a PriorityBinding 
        internal bool IsInPriorityBindingExpression
        { 
            get { return TestFlag(PrivateFlags.iInPriorityBindingExpression); }
        } 
 
        ///  True if this binding expression belongs to a MultiBinding 
        internal bool IsInMultiBindingExpression 
        {
            get { return TestFlag(PrivateFlags.iInMultiBindingExpression); }
        }
 
        ///  True if this binding expression belongs to a PriorityBinding or MultiBinding 
        internal bool IsInBindingExpressionCollection 
        { 
            get { return TestFlag(PrivateFlags.iInPriorityBindingExpression | PrivateFlags.iInMultiBindingExpression); }
        } 

        ///  True if this binding expression validates on exceptions 
        internal bool ValidatesOnExceptions
        { 
            get { return TestFlag(PrivateFlags.iValidatesOnExceptions); }
        } 
 
        ///  True if this binding expression validates on data errors 
        internal bool ValidatesOnDataErrors 
        {
            get { return TestFlag(PrivateFlags.iValidatesOnDataErrors); }
        }
 
        ///  The parent MultiBindingExpression (if any) 
        internal MultiBindingExpression ParentMultiBindingExpression 
        { 
            get { return _parentBindingExpression as MultiBindingExpression; }
        } 

        ///  The parent PriorityBindingExpression (if any) 
        internal PriorityBindingExpression ParentPriorityBindingExpression
        { 
            get { return _parentBindingExpression as PriorityBindingExpression; }
        } 
 
        ///  The parent PriorityBindingExpression or MultiBindingExpression (if any) 
        internal BindingExpressionBase ParentBindingExpressionBase 
        {
            get { return _parentBindingExpression; }
        }
 
        ///  The FallbackValue (from the parent Binding), possibly converted
        /// to a type suitable for the target property. 
        internal object FallbackValue 
        {
            // perf note: we recompute the value every time it's needed.  This is 
            // a good decision if we seldom need the value.  Alternatively we could
            // cache it.  Wait until we know what the perf impact really is.
            get { return ConvertFallbackValue(ParentBindingBase.FallbackValue, TargetProperty, this); }
        } 

        ///  The default value of the target property  
        internal object DefaultValue 
        {
            // perf note: we recompute the value every time it's needed.  This is 
            // a good decision if we seldom need the value.  Alternatively we could
            // cache it.  Wait until we know what the perf impact really is.
            get
            { 
                DependencyObject target = TargetElement;
                if (target != null) 
                { 
                    return TargetProperty.GetDefaultValue(target.DependencyObjectType);
                } 
                return DependencyProperty.UnsetValue;
            }
        }
 
        ///  The effective string format, taking into account the target
        /// property, parent bindings, convenience syntax, etc.  
        internal string EffectiveStringFormat 
        {
            get { return _effectiveStringFormat; } 
        }

        ///  The effective TargetNullValue, taking into account the target
        /// property, parent bindings, etc.  
        internal object EffectiveTargetNullValue
        { 
            get { return _effectiveTargetNullValue; } 
        }
 
        ///  return the root of the tree of {Multi/Priority}BindingExpressions
        internal BindingExpressionBase RootBindingExpression
        {
            get 
            {
                BindingExpressionBase child = this; 
                BindingExpressionBase parent = this.ParentBindingExpressionBase; 
                while (parent != null)
                { 
                    child = parent;
                    parent = child.ParentBindingExpressionBase;
                }
                return child; 
            }
        } 
 
        ///  return the binding group to which this expression belongs (or null) 
        internal BindingGroup BindingGroup 
        {
            get
            {
                BindingExpressionBase root = RootBindingExpression; 
                WeakReference wr = root._bindingGroup;
                return (wr == null) ? null : (BindingGroup)wr.Target; 
            } 
        }
 
        internal virtual bool IsParentBindingUpdateTriggerDefault
        {
            get { return false; }
        } 

        //----------------------------------------------------- 
        // 
        //  Protected Methods
        // 
        //------------------------------------------------------

        /// 
        /// Attach the binding expression to the given target object and property. 
        /// Derived classes should call base.AttachOverride before doing their work.
        ///  
        internal virtual void AttachOverride(DependencyObject target, DependencyProperty dp) 
        {
            _targetElement = new WeakReference(target); 
            _targetProperty = dp;

            // get the engine
            _engine = DataBindEngine.CurrentDataBindEngine; 

            DetermineEffectiveStringFormat(); 
            DetermineEffectiveTargetNullValue(); 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach)) 
            {
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.AttachExpression(
                                        TraceData.Identify(this), 
                                        target.GetType().FullName, dp.Name, AvTrace.GetHashCodeHelper(target)));
            } 
        } 

        ///  
        /// Detach the binding expression from its target object and property.
        /// Derived classes should call base.DetachOverride after doing their work.
        /// 
        internal virtual void DetachOverride() 
        {
            _engine = null; 
            _targetElement = null; 
            _targetProperty = null;
            SetStatus(BindingStatus.Detached); 

            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Attach))
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.DetachExpression(
                                        TraceData.Identify(this))); 
            } 
        }
 
        /// 
        /// Invalidate the given child expression.
        /// 
        internal abstract void InvalidateChild(BindingExpressionBase bindingExpression); 

        ///  
        /// Change the dependency sources for the given child expression. 
        /// 
        internal abstract void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources); 

        /// 
        /// Replace the given child expression with a new one.
        ///  
        internal abstract void ReplaceChild(BindingExpressionBase bindingExpression);
 
        // handle joining or leaving a binding group 
        internal void OnBindingGroupChanged(bool joining)
        { 
            if (joining)
            {
                // joining a binding group:
                // update Explicitly, unless declared otherwise 
                if (IsParentBindingUpdateTriggerDefault)
                { 
                    if (IsUpdateOnLostFocus) 
                    {
                        LostFocusEventManager.RemoveListener(TargetElement, this); 
                    }

                    SetUpdateSourceTrigger(UpdateSourceTrigger.Explicit);
                } 
            }
            else 
            { 
                // leaving a binding group:
                // restore update trigger 
                if (IsParentBindingUpdateTriggerDefault)
                {
                    FrameworkPropertyMetadata fwMetaData = TargetProperty.GetMetadata(TargetElement.DependencyObjectType) as FrameworkPropertyMetadata;
 
                    UpdateSourceTrigger ust = GetDefaultUpdateSourceTrigger(fwMetaData);
                    SetUpdateSourceTrigger(ust); 
 
                    if (IsUpdateOnLostFocus)
                    { 
                        LostFocusEventManager.AddListener(TargetElement, this);
                    }
                }
            } 
        }
 
        // register the leaf bindings with the binding group 
        internal abstract void UpdateBindingGroup(BindingGroup bg);
 
        // transfer a value from target to source
        internal void UpdateValue()
        {
            UpdateValidationError(null); 

            object value = GetRawProposedValue(); 
            if (!Validate(value, ValidationStep.RawProposedValue)) 
                return;
 
            value = ConvertProposedValue(value);
            if (!Validate(value, ValidationStep.ConvertedProposedValue))
                return;
 
            value = UpdateSource(value);
            if (!Validate(value, ValidationStep.UpdatedValue)) 
                return; 

            value = CommitSource(value); 
            if (!Validate(value, ValidationStep.CommittedValue))
                return;

            EndSourceUpdate(); 
        }
 
        ///  
        /// Get the raw proposed value
        ///  
        internal virtual object GetRawProposedValue()
        {
            object value = Value;
 
            // TargetNullValue is the UI representation of a "null" value.  Use null internally.
            if (Object.Equals(value, EffectiveTargetNullValue)) 
            { 
                value = null;
            } 

            return value;
        }
 
        /// 
        /// Get the converted proposed value 
        ///  
        internal abstract object ConvertProposedValue(object rawValue);
 
        /// 
        /// Get the converted proposed value and inform the binding group
        /// 
        internal abstract void ObtainConvertedProposedValue(BindingGroup bindingGroup); 

        ///  
        /// Update the source value 
        /// 
        internal abstract object UpdateSource(object convertedValue); 

        /// 
        /// Update the source value and inform the binding group
        ///  
        internal abstract void UpdateSource(BindingGroup bindingGroup);
 
        ///  
        /// Commit the source value
        ///  
        internal virtual object CommitSource(object value)
        {
            return value;
        } 

        ///  
        /// Store the value in the binding group 
        /// 
        internal abstract void StoreValueInBindingGroup(object value, BindingGroup bindingGroup); 

        /// 
        /// Run validation rules for the given step
        ///  
        internal virtual bool Validate(object value, ValidationStep validationStep)
        { 
            if (value == Binding.DoNothing || value == DependencyProperty.UnsetValue) 
                return true;
 
            // clear errors from this step - we're about to reevaluate those rules
            ClearValidationErrors(validationStep);

            Collection validationRules = ParentBindingBase.ValidationRulesInternal; 

            if (validationRules != null) 
            { 
                CultureInfo culture = GetCulture();
                switch (validationStep) 
                {
                    case ValidationStep.UpdatedValue:
                    case ValidationStep.CommittedValue:
                        // rules at these steps get passed the rule owner 
                        value = this;
                        break; 
                } 

                foreach (ValidationRule validationRule in validationRules) 
                {
                    if (validationRule.ValidationStep == validationStep)
                    {
                        ValidationResult validationResult = validationRule.Validate(value, culture); 

                        if (!validationResult.IsValid) 
                        { 
                            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Update))
                            { 
                                TraceData.Trace(TraceEventType.Warning,
                                                    TraceData.ValidationRuleFailed(
                                                        TraceData.Identify(this),
                                                        TraceData.Identify(validationRule))); 
                            }
 
                            UpdateValidationError( new ValidationError(validationRule, this, validationResult.ErrorContent, null)); 
                            return false; // kenlai:
                        } 
                    }
                }
            }
 
            return true;
        } 
 
        /// 
        /// Run validation rules for the given step, and inform the binding group 
        /// 
        internal abstract bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep);

        ///  
        /// Compute the culture, either from the parent Binding, or from the target element.
        ///  
        internal CultureInfo GetCulture() 
        {
            // lazy initialization, to let the target element acquire all its properties 
            if (_culture == DefaultValueObject)
            {
                // explicit culture set in Binding
                _culture = ParentBindingBase.ConverterCultureInternal; 

                // if that doesn't work, use target element's xml:lang property 
                if (_culture == null) 
                {
                    DependencyObject target = TargetElement; 
                    if (target != null)
                    {
                        if (IsInTransfer && (TargetProperty == FrameworkElement.LanguageProperty))
                        { 
                            // A binding for the Language property needs the value
                            // of the Language property.  This circularity is not 
                            // supported (bug 1274874). 
                            if (TraceData.IsEnabled)
                            { 
                                TraceData.Trace(TraceEventType.Critical, TraceData.RequiresExplicitCulture, TargetProperty.Name, this);
                            }

                            throw new InvalidOperationException(SR.Get(SRID.RequiresExplicitCulture, TargetProperty.Name)); 
                        }
 
                        // cache CultureInfo since requerying an inheritable property on every Transfer/Update can be quite expensive 
                        // CultureInfo DP rarely changes once a XAML document is loaded.
                        // To be 100% correct, changes to the CultureInfo attached DP should be tracked 
                        // and cause a re-evaluation of this binding.
                        _culture = ((XmlLanguage) target.GetValue(FrameworkElement.LanguageProperty)).GetSpecificCulture();
                    }
                } 
            }
            return (CultureInfo)_culture; 
        } 

        ///  Begin a source update  
        internal void BeginSourceUpdate()
        {
            ChangeFlag(PrivateFlags.iInUpdate, true);
        } 

        ///  End a source update  
        internal void EndSourceUpdate() 
        {
            ChangeFlag(PrivateFlags.iInUpdate | PrivateFlags.iNeedUpdate, false); 
        }

        ///  change the value to the new value, and notify listeners 
        internal void ChangeValue(object newValue, bool notify) 
        {
            object oldValue = (_value != DefaultValueObject) ? _value : DependencyProperty.UnsetValue; 
 
            _value = newValue;
 
            if (notify && ValueChanged != null)
            {
                ValueChanged(this, new BindingValueChangedEventArgs(oldValue, newValue));
            } 
        }
 
        ///  the target value has changed - the source needs to be updated  
        internal void Dirty()
        { 
            if (!IsInTransfer)
            {
                NeedsUpdate = true;
                if (IsUpdateOnPropertyChanged) 
                    Update(true);
            } 
        } 

        ///  use the Fallback or Default value, called when a real value is not available  
        internal object UseFallbackValue()
        {
            object value = FallbackValue;
 
            // if there's a problem with the fallback, use Default instead
            if (value == DefaultValueObject) 
            { 
                value = DependencyProperty.UnsetValue;
            } 

            if (value != DependencyProperty.UnsetValue)
            {
                UsingFallbackValue = true; 
            }
            else 
            { 
                // if fallback isn't available, use Default (except when in a binding collection)
                if (Status == BindingStatus.Active) 
                    SetStatus(BindingStatus.UpdateTargetError);

                if (!IsInBindingExpressionCollection)
                { 
                    value = DefaultValue;
 
                    if (TraceData.IsEnabled) 
                    {
                        TraceData.Trace(TraceEventType.Information, TraceData.NoValueToTransfer, this); 
                    }
                }
            }
 
            return value;
        } 
 
        // determine if the given value is "null" (in a general sense)
        internal bool IsNullValue(object value) 
        {
            if (value == null)
                return true;
 
            if (Convert.IsDBNull(value))
                return true; 
 
            if (IsSqlNull(value))
                return true; 

            return false;
        }
 
        // return true if the value is null in the SqlTypes sense
        bool IsSqlNull(object value) 
        { 
            Type type = value.GetType();
            return Engine.IsINullable(type) && IsSqlNullImpl(value); 
        }

        // separate function to avoid loading System.Data unnecessarily
        [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
        static bool IsSqlNullImpl(object value)
        { 
            System.Data.SqlTypes.INullable nullable = value as System.Data.SqlTypes.INullable; 
            return (nullable != null && nullable.IsNull);
        } 

        // determine a "null" value appropriate for the given type
        internal object NullValueForType(Type type)
        { 
            if (type == null)
                return null; 
 
            object sqlNull;
            if (IsSqlNullableType(type, out sqlNull)) 
                return sqlNull;

            if (!type.IsValueType)
                return null; 

            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>)) 
                return null; 

            return DependencyProperty.UnsetValue; 
        }

        // return true if the type is nullable in the SqlTypes sense.  If so, return the null value.
        bool IsSqlNullableType(Type type, out object nullValue) 
        {
            if (Engine.IsINullable(type)) 
            { 
                return IsSqlNullableTypeImpl(type, out nullValue);
            } 
            else
            {
                nullValue = null;
                return false; 
            }
        } 
 
        // separate function to avoid loading System.Data unnecessarily
        [System.Runtime.CompilerServices.MethodImplAttribute(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] 
        static bool IsSqlNullableTypeImpl(Type type, out object nullValue)
        {
            // some SqlTypes are classes with a Null property.  Others are structs with a Null field.  Try both.
            System.Reflection.FieldInfo nullField = type.GetField("Null", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy); 
            if (nullField != null)
            { 
                nullValue = nullField.GetValue(null); 
                return true;
            } 

            System.Reflection.PropertyInfo nullProperty = type.GetProperty("Null", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.FlattenHierarchy);
            if (nullProperty != null)
            { 
                nullValue = nullProperty.GetValue(null, null);
                return true; 
            } 

            nullValue = null; 
            return false;
        }

        internal ValidationRule LookupValidationRule(Type type) 
        {
            ValidationRule result = ParentBindingBase.GetValidationRule(type); 
 
            if (result == null && _parentBindingExpression != null)
            { 
                result = _parentBindingExpression.LookupValidationRule(type);
            }

            return result; 
        }
 
        // discover the binding group (if any) that this binding should join, 
        // and join it.  More precisely, cause the root binding to join.
        internal void JoinBindingGroup(bool isReflective, DependencyObject contextElement) 
        {
            BindingGroup bindingGroup = RootBindingExpression.FindBindingGroup(isReflective, contextElement);

            if (bindingGroup != null) 
            {
                JoinBindingGroup(bindingGroup, /*explicit*/false); 
            } 
        }
 
        // remove the binding from its group
        internal void LeaveBindingGroup()
        {
            BindingExpressionBase root = RootBindingExpression; 
            BindingGroup bg = root.BindingGroup;
            if (bg != null) 
            { 
                bg.BindingExpressions.Remove(root);
                root._bindingGroup = null; 
            }
        }

        // discover the binding group (if any) that this root binding should join. 
        BindingGroup FindBindingGroup(bool isReflective, DependencyObject contextElement)
        { 
            Debug.Assert(RootBindingExpression == this, "Only call this with a root binding"); 

            // if we've already joined (or failed to join) a group, just return the result 
            if (_bindingGroup != null)
            {
                return (BindingGroup)_bindingGroup.Target;
            } 

            BindingGroup bg; 
            string groupName = ParentBindingBase.BindingGroupName; 

            // a null group name means "don't join any group". 
            if (groupName == null)
            {
                MarkAsNonGrouped();
                return null; 
            }
 
            // an empty group name means join by DataContext 
            if (String.IsNullOrEmpty(groupName))
            { 
                // check further preconditions:
                if (!isReflective ||                // must have target-to-source data flow
                    contextElement == null)         // must use data context
                { 
                    // later child bindings might pass this test, so don't mark
                    // this root binding as non-grouped yet 
                    return null; 
                }
 
                // only the innermost binding group is eligible
                bg = (BindingGroup)contextElement.GetValue(FrameworkElement.BindingGroupProperty);
                if (bg == null)
                { 
                    MarkAsNonGrouped();
                    return null; 
                } 

                // the context element must share data context with the group 
                DependencyProperty dataContextDP = FrameworkElement.DataContextProperty;
                DependencyObject groupContextElement = bg.InheritanceContext;
                if (groupContextElement == null ||
                    !Object.Equals( contextElement.GetValue(dataContextDP), 
                                    groupContextElement.GetValue(dataContextDP)))
                { 
                    MarkAsNonGrouped(); 
                    return null;
                } 

                // if the binding survives the gauntlet, return the group
                return bg;
            } 

            // a non-empty group name means join by name 
            else 
            {
                // walk up the tree, looking for a matching binding group 
                DependencyProperty bindingGroupDP = FrameworkElement.BindingGroupProperty;
                FrameworkObject fo = new FrameworkObject(TargetElement);
                while (fo.DO != null)
                { 
                    BindingGroup bgCandidate = (BindingGroup)fo.DO.GetValue(bindingGroupDP);
                    if (bgCandidate == null) 
                    { 
                        MarkAsNonGrouped();
                        return null; 
                    }

                    if (bgCandidate.Name == groupName)
                    { 
                        // return the matching group
                        return bgCandidate; 
                    } 

                    fo = fo.FrameworkParent; 
                }

                // no match - report an error
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error, 
                            TraceData.BindingGroupNameMatchFailed(groupName), 
                            this);
                } 

                MarkAsNonGrouped();
                return null;
            } 
        }
 
        // add a binding to the given binding group 
        internal void JoinBindingGroup(BindingGroup bg, bool explicitJoin)
        { 
            BindingExpressionBase root = null;  // set to non-null by the next loop

            for (   BindingExpressionBase bindingExpr = this;
                    bindingExpr != null; 
                    bindingExpr = bindingExpr.ParentBindingExpressionBase)
            { 
                root = bindingExpr; 

                // bindings in a group update Explicitly, unless declared otherwise 
                bindingExpr.OnBindingGroupChanged(/*joining*/true);

                bg.AddToValueTable(bindingExpr);
            } 

            // add the root binding to the group 
            if (root._bindingGroup == null) 
            {
                // use WeakReference because the BindingGroup contains a strong reference 
                // to the visual tree (via InheritanceContext)
                root._bindingGroup = new WeakReference(bg);

                // when the group is implicitly discovered, always add the root binding to the group's collection. 
                // When the binding is added explicitly - via BindingGroup.BindingExpressions.Add() -
                // check first to see if it has already been added 
                bool addToGroup = explicitJoin ? !bg.BindingExpressions.Contains(root) : true; 
                if (addToGroup)
                { 
                    bg.BindingExpressions.Add(root);
                }

                // in the explicit case, register its items and values with the binding group 
                // (the implicit case does this when the bindings activate)
                if (explicitJoin) 
                { 
                    root.UpdateBindingGroup(bg);
                } 
            }
            else
            {
                if (root.BindingGroup != bg) 
                    throw new InvalidOperationException(SR.Get(SRID.BindingGroup_CannotChangeGroups));
            } 
        } 

        // mark a binding as non-grouped, so that we avoid doing the discovery again 
        void MarkAsNonGrouped()
        {
            // Leaf bindings only get asked once, so there's no need to add a mark
            if (!(this is BindingExpression)) 
            {
                _bindingGroup = new WeakReference(null); 
            } 
        }
 
        /// 
        /// Handle events from the centralized event table
        /// 
        internal virtual bool ReceiveWeakEvent(Type managerType, object sender, EventArgs e) 
        {
            return false;       // unrecognized event 
        } 

        private bool TestFlag(PrivateFlags flag) 
        {
            return (_flags & flag) != 0;
        }
 
        private void ChangeFlag(PrivateFlags flag, bool value)
        { 
            if (value)  _flags |=  flag; 
            else        _flags &= ~flag;
        } 

        //-----------------------------------------------------
        //
        //  Internal Properties 
        //
        //------------------------------------------------------ 
 
        internal DependencyProperty TargetProperty { get { return _targetProperty; } }
 
        // A BindingExpression cannot hold a strong reference to the target element - this
        // leads to memory leaks (bug 871139).  The problem is that BindingExpression and its workers
        // register for events from the data item, creating a reference from
        // the data item to the BindingExpression.  The data item typically has a long lifetime, 
        // so if the BindingExpression held a SR to the target, the target element would
        // also stay alive forever. 
        //      Instead, BindingExpression holds a WeakReference to the target.  This means we 
        // have to check it before dereferencing (here), and cope when the
        // reference fails (in callers to this property).  Requests for the TargetElement 
        // are not trivial, so callers should request it once and cache the result
        // in a local variable.  They should not save it in a global or instance
        // variable of course;  that would defeat the purpose of the WR.
        //      This allows the target element to be GC'd when it's no longer in 
        // use by the tree or application.  The next time the BindingExpression asks for
        // its TargetElement, the WR will fail.  At this point, the BindingExpression is no 
        // longer useful, so it can sever all connections to the outside world (i.e. 
        // stop listening for events).  This allows the BindingExpression itself to be GC'd.
        internal DependencyObject TargetElement 
        {
            get
            {
                if (_targetElement != null) 
                {
                    DependencyObject result = _targetElement.Target as DependencyObject; 
                    if (result != null) 
                        return result;
 
                    // target has been GC'd, sever all connections
                    _targetElement = null;      // prevents re-entry from Detach()
                    Detach();
                } 

                return null; 
            } 
        }
 
        internal WeakReference TargetElementReference
        {
            get { return _targetElement; }
        } 

        internal DataBindEngine Engine 
        { 
            get { return _engine; }
        } 

        internal Dispatcher Dispatcher
        {
            get { return (_engine != null) ? _engine.Dispatcher : null; } 
        }
 
        internal object Value 
        {
            get 
            {
                if (_value == DefaultValueObject)
                {
                    // don't notify listeners.  This isn't a real value change. 
                    ChangeValue(UseFallbackValue(), false /*notify*/);
                } 
                return _value; 
            }
            set 
            {
                ChangeValue(value, true);
                Dirty();
            } 
        }
 
        internal WeakDependencySource[] WeakSources 
        {
            get { return _sources; } 
        }

        /// 
        ///     NoTarget DependencyProperty, a placeholder used by BindingExpressions with no target property 
        /// 
        internal static readonly DependencyProperty NoTargetProperty = 
                DependencyProperty.RegisterAttached("NoTarget", typeof(object), typeof(BindingExpressionBase), 
                                            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.None));
 
        internal TraceLog TraceLog { get { return _traceLog; } }

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

        ///  
        /// Attach the binding expression to the given target object and property.
        /// 
        internal void Attach(DependencyObject target, DependencyProperty dp)
        { 
            // make sure we're on the right thread to access the target
            if (target != null) 
            { 
                target.VerifyAccess();
            } 

            IsAttaching = true;
            AttachOverride(target, dp);
            IsAttaching = false; 
        }
 
        ///  
        /// Detach the binding expression from its target object and property.
        ///  
        internal void Detach()
        {
            if (_status == BindingStatus.Detached || IsDetaching)
                return; 

            IsDetaching = true; 
            DetachOverride(); 
            IsDetaching = false;
        } 

        internal void SetStatus(BindingStatus status)
        {
            if (_status == BindingStatus.Detached && status != _status) 
            {
                throw new InvalidOperationException(SR.Get(SRID.BindingExpressionStatusChanged, _status, status)); 
            } 

            _status = status; 

            if (_traceLog != null)
            {
                _traceLog.Add("Set status = {0} {1}", _status, new StackTrace()); 
            }
        } 
 
        // convert a user-supplied fallback value to a usable equivalent
        //  returns:    UnsetValue          if user did not supply a fallback value 
        //              value               if fallback value is legal
        //              DefaultValueObject  otherwise
        internal static object ConvertFallbackValue(object value, DependencyProperty dp, object sender)
        { 
            Exception e;
            object result = ConvertValue(value, dp, out e); 
 
            if (result == DefaultValueObject)
            { 
                if (TraceData.IsEnabled)
                {
                    TraceData.Trace(TraceEventType.Error,
                            TraceData.FallbackConversionFailed( 
                                AvTrace.ToStringHelper(value),
                                AvTrace.TypeName(value), 
                                dp.Name, 
                                dp.PropertyType.Name),
                            sender, e); 
                }
            }

            return result; 
        }
 
        // convert a user-supplied TargetNullValue to a usable equivalent 
        //  returns:    UnsetValue          if user did not supply a fallback value
        //              value               if fallback value is legal 
        //              DefaultValueObject  otherwise
        internal static object ConvertTargetNullValue(object value, DependencyProperty dp, object sender)
        {
            Exception e; 
            object result = ConvertValue(value, dp, out e);
 
            if (result == DefaultValueObject) 
            {
                if (TraceData.IsEnabled) 
                {
                    TraceData.Trace(TraceEventType.Error,
                            TraceData.TargetNullValueConversionFailed(
                                AvTrace.ToStringHelper(value), 
                                AvTrace.TypeName(value),
                                dp.Name, 
                                dp.PropertyType.Name), 
                            sender, e);
                } 
            }

            return result;
        } 

        static object ConvertValue(object value, DependencyProperty dp, out Exception e) 
        { 
            object result;
            e = null; 

            if (value == DependencyProperty.UnsetValue || dp.IsValidValue(value))
            {
                result = value; 
            }
            else 
            { 
                result = null;  // placeholder to keep compiler happy
                // if value isn't the right type, use a type converter to get a better value 
                bool success = false;
                TypeConverter converter = DefaultValueConverter.GetConverter(dp.PropertyType);
                if (converter != null && converter.CanConvertFrom(value.GetType()))
                { 
                    // 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 
                    {
                        result = converter.ConvertFrom(null, CultureInfo.InvariantCulture, value); 
                        success = dp.IsValidValue(result); 
                    }
 
                    // Catch all exceptions.  If we can't convert the fallback value, it doesn't
                    // matter why not;  we should always use the default value instead.
                    // (See bug 1853628 for an example of a converter that throws
                    // an exception not mentioned in the documentation for ConvertFrom.) 
                    catch (Exception ex)
                    { 
                        e = ex; 
                    }
                    catch // non CLS compliant exception 
                    {
                    }

                    #pragma warning restore 56500 
                    #pragma warning restore 1634, 1691
                } 
 
                if (!success)
                { 
                    // if can't convert it, don't use it
                    result = DefaultValueObject;
                }
            } 

            return result; 
        } 

        // Certain trace reports should be marked as 'error' unless the binding 
        // is prepared to handle it in some way (e.g. FallbackValue), in which
        // case 'warning'.
        internal TraceEventType TraceLevel
        { 
            get
            { 
                // FallbackValue is present 
                if (ParentBindingBase.FallbackValue != DependencyProperty.UnsetValue)
                    return TraceEventType.Warning; 

                // Binding is a member of MultiBinding or PriorityBinding
                if (IsInBindingExpressionCollection)
                    return TraceEventType.Warning; 

                // all other cases - error 
                return TraceEventType.Error; 
            }
        } 

        internal virtual void Activate()
        {
        } 

        internal virtual void Deactivate() 
        { 
        }
 
        internal virtual void Update(bool synchronous)
        {
        }
 
        internal void UpdateValidationError(ValidationError validationError)
        { 
            if (_validationError != null) 
            {
                ValidationError oldValidationError = _validationError; 
                _validationError = null;    // clear before raising events, so that HasError is correct
                RemoveValidationError(oldValidationError);
            }
 
            _validationError = validationError;
 
            if (_validationError != null) 
            {
                AddValidationError(_validationError); 
            }
        }

        internal void AddValidationError(ValidationError validationError) 
        {
            // add the error to the target element 
            Validation.AddValidationError(validationError, TargetElement, NotifyOnValidationError); 

            // add the error to the binding group's target element 
            BindingGroup bindingGroup = BindingGroup;
            if (bindingGroup != null)
            {
                bindingGroup.AddValidationError(validationError); 
            }
        } 
 
        internal void RemoveValidationError(ValidationError validationError)
        { 
            // remove the error from the target element
            Validation.RemoveValidationError(validationError, TargetElement, NotifyOnValidationError);

            // remove the error from the binding group's target element 
            BindingGroup bindingGroup = BindingGroup;
            if (bindingGroup != null) 
            { 
                bindingGroup.RemoveValidationError(validationError);
            } 
        }

        // remove all errors raised at the given step, in preparation for running
        // the rules at that step 
        internal void ClearValidationErrors(ValidationStep validationStep)
        { 
            if (_validationError == null || _validationError.RuleInError.ValidationStep != validationStep) 
                return;
 
            RemoveValidationError(_validationError);
            _validationError = null;
        }
 
        internal void ChangeSources(WeakDependencySource[] newSources)
        { 
            if (IsInBindingExpressionCollection) 
                ParentBindingExpressionBase.ChangeSourcesForChild(this, newSources);
            else 
                ChangeSources(TargetElement, TargetProperty, newSources);

            // store the sources with weak refs, so they don't cause memory leaks (bug 980041)
            _sources = newSources; 
        }
 
        ///  
        /// combine the sources of BindingExpressions, using new sources for
        /// the BindingExpression at the given index 
        /// 
        /// -1 to indicate no new sources
        /// collection of child binding expressions 
        /// how many child expressions to include 
        /// use null when no new sources
        ///  
        internal static WeakDependencySource[] CombineSources(int index, Collection bindingExpressions, int count, WeakDependencySource[] newSources) 
        {
            if (index == count) 
            {
                // Be sure to include newSources if they are being appended
                count++;
            } 

            Collection tempList = new Collection(); 
 
            for (int i = 0; i < count; ++i)
            { 
                BindingExpressionBase bindExpr = bindingExpressions[i];
                WeakDependencySource[] sources = (i==index) ? newSources :
                                            (bindExpr != null) ? bindExpr.WeakSources :
                                            null; 
                int m = (sources == null) ? 0 : sources.Length;
                for (int j = 0; j < m; ++j) 
                { 
                    WeakDependencySource candidate = sources[j];
 
                    // don't add duplicate source
                    for (int k = 0; k < tempList.Count; ++k)
                    {
                        WeakDependencySource prior = tempList[k]; 
                        if (candidate.DependencyObject == prior.DependencyObject &&
                            candidate.DependencyProperty == prior.DependencyProperty) 
                        { 
                            candidate = null;
                            break; 
                        }
                    }

                    if (candidate != null) 
                        tempList.Add(candidate);
                } 
            } 

            WeakDependencySource[] result; 
            if (tempList.Count > 0)
            {
                result = new WeakDependencySource[tempList.Count];
                tempList.CopyTo(result, 0); 
                tempList.Clear();
            } 
            else 
            {
                result = null; 
            }

            return result;
        } 

        internal void ResolvePropertyDefaultSettings(BindingMode mode, UpdateSourceTrigger updateTrigger, FrameworkPropertyMetadata fwMetaData) 
        { 
            // resolve "property-default" dataflow
            if (mode == BindingMode.Default) 
            {
                BindingFlags f = BindingFlags.OneWay;
                if (fwMetaData != null && fwMetaData.BindsTwoWayByDefault)
                { 
                    f = BindingFlags.TwoWay;
                } 
 
                ChangeFlag(PrivateFlags.iPropagationMask, false);
                ChangeFlag((PrivateFlags)f, true); 

                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ResolveDefaults))
                {
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.ResolveDefaultMode(
                                            TraceData.Identify(this), 
                                            (f == BindingFlags.OneWay) ? BindingMode.OneWay : BindingMode.TwoWay)); 
                }
            } 

            Debug.Assert((_flags & PrivateFlags.iPropagationMask) != PrivateFlags.iPropDefault,
                "BindingExpression should not have Default propagation");
 
            // resolve "property-default" update trigger
            if (updateTrigger == UpdateSourceTrigger.Default) 
            { 
                UpdateSourceTrigger ust = GetDefaultUpdateSourceTrigger(fwMetaData);
 
                SetUpdateSourceTrigger(ust);

                if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.ResolveDefaults))
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.ResolveDefaultUpdate( 
                                            TraceData.Identify(this), 
                                            ust));
                } 
            }

            Invariant.Assert((_flags & PrivateFlags.iUpdateMask) != PrivateFlags.iUpdateDefault,
                "BindingExpression should not have Default update trigger"); 
        }
 
        // return the effective update trigger, used when binding doesn't set one explicitly 
        internal UpdateSourceTrigger GetDefaultUpdateSourceTrigger(FrameworkPropertyMetadata fwMetaData)
        { 
            UpdateSourceTrigger ust =
                IsInMultiBindingExpression ? UpdateSourceTrigger.Explicit :
                (fwMetaData != null) ? fwMetaData.DefaultUpdateSourceTrigger :
                                    UpdateSourceTrigger.PropertyChanged; 
            return ust;
        } 
 
        internal void SetUpdateSourceTrigger(UpdateSourceTrigger ust)
        { 
            ChangeFlag(PrivateFlags.iUpdateMask, false);
            ChangeFlag((PrivateFlags)BindingBase.FlagsFrom(ust), true);
        }
 
        internal void DetermineEffectiveStringFormat()
        { 
            Type targetType = TargetProperty.PropertyType; 
            if (targetType != typeof(String))
            { 
                // if the target type isn't String, we don't need a string format
                return; // _effectiveStringFormat is already null
            }
 
            // determine the effective target type and the declared string format
            // by looking up the tree of binding expressions 
            string stringFormat = ParentBindingBase.StringFormat; 
            BindingExpressionBase be = this.ParentBindingExpressionBase;
 
            while (be != null)
            {
                if (be is MultiBindingExpression)
                { 
                    // MultiBindings should receive object values, not string
                    targetType = typeof(Object); 
                    break; 
                }
                else if (stringFormat == null && be is PriorityBindingExpression) 
                {
                    // use a PriorityBinding's string format, unless we already
                    // have a more specific one
                    stringFormat = be.ParentBindingBase.StringFormat; 
                }
 
                be = be.ParentBindingExpressionBase; 
            }
 
            // if we need a string format, cache it
            if (targetType == typeof(String))
            {
                #if NotToday 
                // special case: when these conditions all apply
                //      a) target element belongs to a DataTemplate 
                //      b) template was found by implicit (type-based) lookup 
                //      c) container (ContentPresenter) has a string format
                //      d) binding has no effective string format 
                // then use the CP's string format.  This enables scenarios like
                //      
                //           
                //      
                // where you'd like to control the format at the point of use, 
                // rather than at the point of template declaration.  This is 
                // especially useful when the template is declared in a global place
                // like app resources or a theme file.  In particular it makes the 
                // GroupStyle.HeaderStringFormat property work;  the template for
                // GroupItem is defined in the theme, but needs to pick up formatting
                // from the app's markup.
 
                if (stringFormat == null)   // (d)
                { 
                    FrameworkObject fo = new FrameworkObject(TargetElement); 
                    ContentPresenter cp = fo.TemplatedParent as ContentPresenter;
                    if (cp != null &&                       // (a) 
                        cp.ContentStringFormat != null)     // (c)
                    {
                        DataTemplate dt = cp.TemplateInternal as DataTemplate;
                        if (dt != null &&                   // (a) 
                            dt.DataType != null)            // (b)
                        { 
                            stringFormat = cp.ContentStringFormat; 
                        }
                    } 
                }
                #endif

                if (!String.IsNullOrEmpty(stringFormat)) 
                {
                    _effectiveStringFormat = Helper.GetEffectiveStringFormat(stringFormat); 
                } 
            }
        } 

        internal void DetermineEffectiveTargetNullValue()
        {
            Type targetType = TargetProperty.PropertyType; 

            // determine the effective target type and the declared TargetNullValue 
            // by looking up the tree of binding expressions 
            object targetNullValue = ParentBindingBase.TargetNullValue;
            BindingExpressionBase be = this.ParentBindingExpressionBase; 

            while (be != null)
            {
                if (be is MultiBindingExpression) 
                {
                    // MultiBindings should receive object values 
                    targetType = typeof(Object); 
                    break;
                } 
                else if (targetNullValue == DependencyProperty.UnsetValue && be is PriorityBindingExpression)
                {
                    // use a PriorityBinding's TargetNullValue, unless we already
                    // have a more specific one 
                    targetNullValue = be.ParentBindingBase.TargetNullValue;
                } 
 
                be = be.ParentBindingExpressionBase;
            } 

            // if user declared a TargetNullValue, make sure it has the right type.
            if (targetNullValue != DependencyProperty.UnsetValue)
            { 
                targetNullValue = ConvertTargetNullValue(targetNullValue, TargetProperty, this);
                if (targetNullValue == DefaultValueObject) 
                { 
                    // if not, ignore it (having logged a trace message)
                    targetNullValue = DependencyProperty.UnsetValue; 
                }
            }

            // for back-compat, don't turn on TargetNullValue unless user explicitly 
            // asks for it.  This means users have to add TargetNullValue to get
            // pretty basic scenarios to work (e.g. binding a TextBox to a database 
            // string field that supports DBNull).  It's painful, but can't be 
            // helped.
            #if TargetNullValueBC //BreakingChange 
            // if no declared (or poorly declared) value, make one up
            if (targetNullValue == DependencyProperty.UnsetValue)
            {
                targetNullValue = NullValueForType(targetType); 
            }
            #endif 
 
            _effectiveTargetNullValue = targetNullValue;
        } 

        // To prevent memory leaks, we store WeakReferences to certain objects
        // in various places:  _dataItem, _sources, worker fields.  The logic
        // for this is centralized in these two static methods.  (See bug 940041) 

        internal static object CreateReference(object item) 
        { 
            // One source of leaks is the reference cycle formed when a BindingExpression's
            // source item contains a reference chain to the target element: 
            //      target -> BindingExpression -> source item -> target
            //
            // Making the second link into a WeakReference incurs some cost,
            // so it should be avoided if we know the third link never exists. 
            // We definitely can't avoid this when the item is a DependencyObject,
            // since it's reasonably common for the third link to occur (e.g. 
            // a ContextMenu contains a link to its Popup, which has a property 
            // bound back to the ContextMenu).
            // 
            // For safety, we choose to use WeakRef all the time, unless the item is null.
            // Exception (bug 1124954):  Keep a strong reference to
            // BindingListCollectionView - this keeps the underlying DataView
            // alive, when nobody else will. 
            // Exception (bug 1970505):  Don't allocate a WeakRef for the common
            // case of the NullDataItem 
 
            if (item != null &&
                !(item is BindingListCollectionView) && 
                !(item == BindingExpression.NullDataItem))
            {
                item = new WeakReference(item);
            } 

#if USE_ITEM_REFERENCE 
            item = new ItemReference(item); 
#endif
 
            return item;
        }

        // like CreateReference, but use an existing WeakReference 
        internal static object CreateReference(WeakReference item)
        { 
            object result = item; 
#if USE_ITEM_REFERENCE
            result = new ItemReference(item); 
#endif
            return result;
        }
 
        // like CreateReference, except re-target the old WeakReference (if any)
        internal static object ReplaceReference(object oldReference, object item) 
        { 
            if (item != null &&
                !(item is BindingListCollectionView) && 
                !(item == BindingExpression.NullDataItem))
            {
#if USE_ITEM_REFERENCE
                // if this cast fails, it's because you have done a direct assignment of an 
                // item to some field instead of assigning the result of CreateReference.
                oldReference = ((ItemReference)oldReference).Item; 
#endif 
                WeakReference wr = oldReference as WeakReference;
                if (wr != null) 
                {
                    wr.Target = item;
                    item = wr;
                } 
                else
                { 
                    item = new WeakReference(item); 
                }
            } 

#if USE_ITEM_REFERENCE
            item = new ItemReference(item);
#endif 

            return item; 
        } 

        internal static object GetReference(object reference) 
        {
            if (reference == null)
                return null;
 
#if USE_ITEM_REFERENCE
            // if this cast fails, it's because you have done a direct assignment of an 
            // item to some field instead of assigning the result of CreateReference. 
            reference = ((ItemReference)reference).Item;
#endif 

            WeakReference wr = reference as WeakReference;
            if (wr != null)
                return wr.Target; 
            else
                return reference; 
        } 

        internal static void InitializeTracing(BindingExpressionBase expr, DependencyObject d, DependencyProperty dp) 
        {
            BindingBase parent = expr.ParentBindingBase;
        }
 
        //------------------------------------------------------
        // 
        //  Private Methods 
        //
        //----------------------------------------------------- 

#if USE_ITEM_REFERENCE

        private class ItemReference 
        {
            internal ItemReference(object item) 
            { 
                _item = item;
            } 

            internal object Item { get { return _item; } }

            object _item; 
        }
 
#endif 

        // change WeakDependencySources to (strong) DependencySources, and notify 
        // the property engine about the new sources
        void ChangeSources(DependencyObject target, DependencyProperty dp, WeakDependencySource[] newSources)
        {
            DependencySource[] sources; 

            if (newSources != null) 
            { 
                // convert weak reference to strong
                sources = new DependencySource[newSources.Length]; 
                int n = 0;
                for (int i = 0; i < newSources.Length; ++i)
                {
                    DependencyObject sourceDO = newSources[i].DependencyObject; 
                    if (sourceDO != null)
                    { 
                        // only include sources that are still alive 
                        sources[n++] = new DependencySource(sourceDO, newSources[i].DependencyProperty);
                    } 
                }

                // if any of the sources were no longer alive, trim the array
                if (n < newSources.Length) 
                {
                    DependencySource[] temp; 
                    if (n > 0) 
                    {
                        temp = new DependencySource[n]; 
                        Array.Copy(sources, 0, temp, 0, n);
                    }
                    else
                    { 
                        temp = null;
                    } 
 
                    sources = temp;
                } 
            }
            else
            {
                sources = null; 
            }
 
            // notify property engine 
            ChangeSources(target, dp, sources);
        } 

        // this method is here just to avoid the compiler error
        // error CS0649: Warning as Error: Field 'System.Windows.Data.BindingExpression._traceLog' is never assigned to, and will always have its default value null
        void InitializeTraceLog() 
        {
            _traceLog = new TraceLog(20); 
        } 

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

        BindingBase         _binding; 
        WeakReference       _targetElement; 
        DependencyProperty  _targetProperty;
        DataBindEngine      _engine; 
        PrivateFlags        _flags;
        BindingExpressionBase _parentBindingExpression;
        object              _value = DefaultValueObject;
        BindingStatus       _status; 
        TraceLog            _traceLog;
        ValidationError     _validationError; 
        WeakDependencySource[]  _sources; 
        string              _effectiveStringFormat;
        object              _effectiveTargetNullValue; 
        WeakReference       _bindingGroup;

        object                  _culture = DefaultValueObject;
 
        ///  Sentinel meaning "field has its default value" 
        internal static readonly object DefaultValueObject = new object(); 
    } 

} 


// 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