PriorityBindingExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Defines PriorityBindingExpression object, which chooses a BindingExpression out 
//              of a list of BindingExpressions in order of "priority" (and falls back 
//              to the next BindingExpression as each BindingExpression fails)
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
 
using System;
using System.Collections; 
using System.Collections.ObjectModel;   // Collection 
using System.Diagnostics;
using System.Threading; 
using System.Windows.Controls;          // ValidationStep
using System.Windows.Threading;
using System.Windows.Markup;
using MS.Internal; 
using MS.Internal.Data;
using MS.Utility; 
 
namespace System.Windows.Data
{ 

/// 
///  Describes a collection of BindingExpressions attached to a single property.
///     These behave as "priority" BindingExpressions, meaning that the property 
///     receives its value from the first BindingExpression in the collection that
///     can produce a legal value. 
///  
public sealed class PriorityBindingExpression : BindingExpressionBase
{ 

    //-----------------------------------------------------
    //
    //  Constructors 
    //
    //----------------------------------------------------- 
 
    private PriorityBindingExpression(PriorityBinding binding, BindingExpressionBase owner)
        : base(binding, owner) 
    {
    }

    //------------------------------------------------------ 
    //
    //  Public Properties 
    // 
    //-----------------------------------------------------
 
    ///  Binding from which this expression was created 
    public PriorityBinding ParentPriorityBinding { get { return (PriorityBinding)ParentBindingBase; } }

    ///  List of inner BindingExpression  
    public ReadOnlyCollection   BindingExpressions
    { 
        get { return new ReadOnlyCollection(MutableBindingExpressions); } 
    }
 
    ///  Returns the active BindingExpression (or null) 
    public BindingExpressionBase ActiveBindingExpression
    {
        get { return (_activeIndex < 0) ? null : MutableBindingExpressions[_activeIndex]; } 
    }
 
    //------------------------------------------------------ 
    //
    //  Public Methods 
    //
    //------------------------------------------------------

    ///  Force a data transfer from source to target  
    public override void UpdateTarget()
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            bindExpr.UpdateTarget();
        }
    }
 
    ///  Send the current value back to the source 
    ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource  
    public override void UpdateSource() 
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        {
            bindExpr.UpdateSource();
        } 
    }
 
#region Expression overrides 

    ///  
    ///     Called to evaluate the Expression value
    /// 
    /// DependencyObject being queried
    /// Property being queried 
    /// Computed value. Unset if unavailable.
    internal override object GetValue(DependencyObject d, DependencyProperty dp) 
    { 
        return Value;
    } 

    /// 
    ///     Allows Expression to store set values
    ///  
    /// DependencyObject being set
    /// Property being set 
    /// Value being set 
    /// true if Expression handled storing of the value
    internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value) 
    {
        bool result;
        BindingExpressionBase bindExpr = ActiveBindingExpression;
 
        if (bindExpr != null)
        { 
            result = bindExpr.SetValue(d, dp, value); 
            if (result)
            { 
                // the active binding's value becomes the value of the priority binding
                Value = bindExpr.Value;
            }
        } 
        else
        { 
            // If we couldn't find the active binding, just return true to keep the property 
            // engine from removing the PriorityBinding.
            result = true; 
        }

        return result;
    } 

#endregion  Expression overrides 
 
    //-----------------------------------------------------
    // 
    //  Internal Methods
    //
    //------------------------------------------------------
 
    // Create a new BindingExpression from the given Binding description
    internal static PriorityBindingExpression CreateBindingExpression(DependencyObject d, DependencyProperty dp, PriorityBinding binding, BindingExpressionBase owner) 
    { 
        FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata;
 
        if ((fwMetaData != null && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly)
            throw new ArgumentException(SR.Get(SRID.PropertyNotBindable, dp.Name), "dp");

        // create the BindingExpression 
        PriorityBindingExpression bindExpr = new PriorityBindingExpression(binding, owner);
 
        return bindExpr; 
    }
 
    //-----------------------------------------------------
    //
    //  Protected Internal Properties
    // 
    //-----------------------------------------------------
 
    ///  
    ///     Number of BindingExpressions that have been attached and are listening
    ///  
    internal int AttentiveBindingExpressions
    {
        get { return (_activeIndex == NoActiveBindingExpressions) ? MutableBindingExpressions.Count : _activeIndex + 1; }
    } 

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

    /// 
    ///     Attach a BindingExpression to the given target (element, property) 
    /// 
    /// DependencyObject being set 
    /// Property being set 
    internal override bool AttachOverride(DependencyObject d, DependencyProperty dp)
    { 
        if (!base.AttachOverride(d, dp))
            return false;

        DependencyObject target = TargetElement; 
        if (target == null)
            return false; 
 
        SetStatus(BindingStatus.Active);
 
        int count = ParentPriorityBinding.Bindings.Count;
        _activeIndex = NoActiveBindingExpressions;
        Debug.Assert(MutableBindingExpressions.Count == 0, "expect to encounter empty BindingExpression collection when attaching MultiBinding");
        for (int i = 0; i < count; ++i) 
        {
            AttachBindingExpression(i, false);   // create new binding and have it added to end 
        } 

        return true; 
    }

    ///  sever all connections 
    internal override void DetachOverride() 
    {
        // Theoretically, we only need to detach number of AttentiveBindings, 
        // but we'll traverse the whole list anyway and do aggressive clean-up. 
        int count = MutableBindingExpressions.Count;
        for (int i = 0; i < count; ++i) 
        {
            BindingExpressionBase b = MutableBindingExpressions[i];
            if (b != null)
                b.Detach(); 
        }
 
        ChangeSources(null); 

        base.DetachOverride(); 
    }

    /// 
    /// Invalidate the given child expression. 
    /// 
    internal override void InvalidateChild(BindingExpressionBase bindingExpression) 
    { 
        // Prevent re-entrancy, because ChooseActiveBindingExpression() may
        // activate/deactivate a BindingExpression that indirectly calls this again. 
        if (_isInInvalidateBinding)
            return;
        _isInInvalidateBinding = true;
 
        int index = MutableBindingExpressions.IndexOf(bindingExpression);
        DependencyObject target = TargetElement; 
 
        if (target != null && 0 <= index && index < AttentiveBindingExpressions)
        { 
            // Optimization: only look for new ActiveBindingExpression when necessary:
            // 1. it is a higher priority BindingExpression (or there's no ActiveBindingExpression), or
            // 2. the existing ActiveBindingExpression is broken
            if (    index != _activeIndex 
                ||  (bindingExpression.Status != BindingStatus.Active && !bindingExpression.UsingFallbackValue))
            { 
                ChooseActiveBindingExpression(target); 
            }
 
            // update the value
            UsingFallbackValue = false;
            BindingExpressionBase bindExpr = ActiveBindingExpression;
            object newValue = (bindExpr != null) ? bindExpr.GetValue(target, TargetProperty) : UseFallbackValue(); 
            ChangeValue(newValue, true);
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Transfer)) 
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.PriorityTransfer(
                                        TraceData.Identify(this),
                                        TraceData.Identify(newValue),
                                        _activeIndex, 
                                        TraceData.Identify(bindExpr)));
            } 
 
            // don't invalidate during Attach.  The property engine does it
            // already, and it would interfere with the on-demand activation 
            // of style-defined BindingExpressions.
            if (!IsAttaching)
            {
                // recompute expression 
                target.InvalidateProperty(TargetProperty);
            } 
        } 

        _isInInvalidateBinding = false; 
    }

    /// 
    /// Change the dependency sources for the given child expression. 
    /// 
    internal override void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources) 
    { 
        int index = MutableBindingExpressions.IndexOf(bindingExpression);
 
        if (index >= 0)
        {
            WeakDependencySource[] combinedSources = CombineSources(index, MutableBindingExpressions, AttentiveBindingExpressions, newSources);
            ChangeSources(combinedSources); 
        }
    } 
 
    /// 
    /// Replace the given child expression with a new one. 
    /// 
    internal override void ReplaceChild(BindingExpressionBase bindingExpression)
    {
        int index = MutableBindingExpressions.IndexOf(bindingExpression); 
        DependencyObject target = TargetElement;
 
        if (index >= 0 && target != null) 
        {
            // clean up the old BindingExpression 
            bindingExpression.Detach();

            // create a replacement BindingExpression and put it in the collection
            bindingExpression = AttachBindingExpression(index, true); 
        }
    } 
 
    // register the leaf bindings with the binding group
    internal override void UpdateBindingGroup(BindingGroup bg) 
    {
        for (int i=0, n=MutableBindingExpressions.Count-1; i
    /// Get the raw proposed value 
    /// 
    internal override object GetRawProposedValue()
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            return bindExpr.GetRawProposedValue(); 
        }
        return DependencyProperty.UnsetValue; 
    }

    /// 
    /// Get the converted proposed value 
    /// 
    internal override object ConvertProposedValue(object rawValue) 
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ConvertProposedValue(rawValue);
        }
        return DependencyProperty.UnsetValue; 
    }
 
    ///  
    /// Get the converted proposed value and inform the binding group
    ///  
    internal override bool ObtainConvertedProposedValue(BindingGroup bindingGroup)
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ObtainConvertedProposedValue(bindingGroup); 
        } 

        return true; 
    }

    /// 
    /// Update the source value 
    /// 
    internal override object UpdateSource(object convertedValue) 
    { 
        object result;
        BindingExpressionBase bindExpr = ActiveBindingExpression; 

        if (bindExpr != null)
        {
            result = bindExpr.UpdateSource(convertedValue); 

            if (bindExpr.Status == BindingStatus.UpdateSourceError) 
            { 
                SetStatus(BindingStatus.UpdateSourceError);
            } 
        }
        else
        {
            result = DependencyProperty.UnsetValue; 
        }
 
        return result; 
    }
 
    /// 
    /// Update the source value and inform the binding group
    /// 
    internal override bool UpdateSource(BindingGroup bindingGroup) 
    {
        bool result = true; 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            result = bindExpr.UpdateSource(bindingGroup);

            if (bindExpr.Status == BindingStatus.UpdateSourceError)
            { 
                SetStatus(BindingStatus.UpdateSourceError);
            } 
        } 
        return result;
    } 

    /// 
    /// Store the value in the binding group
    ///  
    internal override void StoreValueInBindingGroup(object value, BindingGroup bindingGroup)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            bindExpr.StoreValueInBindingGroup(value, bindingGroup);
        }
    }
 
    /// 
    /// Run validation rules for the given step 
    ///  
    internal override bool Validate(object value, ValidationStep validationStep)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null)
        {
            return bindExpr.Validate(value, validationStep); 
        }
        return true; 
    } 

    ///  
    /// Run validation rules for the given step, and inform the binding group
    /// 
    internal override bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        { 
            return bindExpr.CheckValidationRules(bindingGroup, validationStep);
        } 
        return true;
    }

    ///  
    /// Get the proposed value(s) that would be written to the source(s), applying
    /// conversion and checking UI-side validation rules. 
    ///  
    internal override bool ValidateAndConvertProposedValue(out Collection values)
    { 
        Debug.Assert(NeedsValidation, "check NeedsValidation before calling this");

        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ValidateAndConvertProposedValue(out values); 
        } 

        values = null; 
        return true;
    }

    //----------------------------------------------------- 
    //
    //  Private Properties 
    // 
    //------------------------------------------------------
 
    /// 
    /// expose a mutable version of the list of all BindingExpressions;
    /// derived internal classes need to be able to populate this list
    ///  
    private Collection MutableBindingExpressions
    { 
        get { return _list; } 
    }
 
    //------------------------------------------------------
    //
    //  Private Methods
    // 
    //-----------------------------------------------------
 
 
    // Create a BindingExpression for position i
    BindingExpressionBase AttachBindingExpression(int i, bool replaceExisting) 
    {
        DependencyObject target = TargetElement;
        if (target == null)
            return null; 

        BindingBase binding = ParentPriorityBinding.Bindings[i]; 
 
        BindingExpressionBase bindExpr = binding.CreateBindingExpression(target, TargetProperty, this);
        if (replaceExisting) // replace exisiting or add as new binding? 
            MutableBindingExpressions[i] = bindExpr;
        else
            MutableBindingExpressions.Add(bindExpr);
 
        bindExpr.Attach(target, TargetProperty);
        return bindExpr; 
    } 

    // Re-evaluate the choice of active BindingExpression 
    void ChooseActiveBindingExpression(DependencyObject target)
    {
        int i, count = MutableBindingExpressions.Count;
        for (i = 0; i < count; ++i) 
        {
            BindingExpressionBase bindExpr = MutableBindingExpressions[i]; 
 
            // Try to activate the BindingExpression if it isn't already activate
            if (bindExpr.Status == BindingStatus.Inactive) 
                bindExpr.Activate();

            if (bindExpr.Status == BindingStatus.Active || bindExpr.UsingFallbackValue)
                break; 
        }
 
        int newActiveIndex = (i < count) ? i : NoActiveBindingExpressions; 

        // if active changes, tell the property engine the new list of sources 
        if (newActiveIndex != _activeIndex)
        {
            int oldActiveIndex = _activeIndex;
 
            // get new list of sources
            _activeIndex = newActiveIndex; 
            WeakDependencySource[] newSources = CombineSources(-1, MutableBindingExpressions, AttentiveBindingExpressions, null); 

            // tell property engine 
            ChangeSources(newSources);

            // deactivate BindingExpressions that don't need to be attentive
            // 
            if (newActiveIndex != NoActiveBindingExpressions)
                for (i = oldActiveIndex; i > newActiveIndex; --i) 
                    MutableBindingExpressions[i].Deactivate(); 
        }
    } 

    private void ChangeValue()
    {
    } 

    internal override void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args) 
    { 
        DependencyProperty dp = args.Property;
        int n = AttentiveBindingExpressions; 

        if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
        {
            TraceData.Trace(TraceEventType.Warning, 
                                TraceData.GotPropertyChanged(
                                    TraceData.Identify(this), 
                                    TraceData.Identify(d), 
                                    dp.Name));
        } 

        for (int i=0; i  _list = new Collection(); 
    int         _activeIndex            = UnknownActiveBindingExpression;
    bool        _isInInvalidateBinding  = false; 
} 

} 

// 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 PriorityBindingExpression object, which chooses a BindingExpression out 
//              of a list of BindingExpressions in order of "priority" (and falls back 
//              to the next BindingExpression as each BindingExpression fails)
// 
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht
//
//---------------------------------------------------------------------------
 
using System;
using System.Collections; 
using System.Collections.ObjectModel;   // Collection 
using System.Diagnostics;
using System.Threading; 
using System.Windows.Controls;          // ValidationStep
using System.Windows.Threading;
using System.Windows.Markup;
using MS.Internal; 
using MS.Internal.Data;
using MS.Utility; 
 
namespace System.Windows.Data
{ 

/// 
///  Describes a collection of BindingExpressions attached to a single property.
///     These behave as "priority" BindingExpressions, meaning that the property 
///     receives its value from the first BindingExpression in the collection that
///     can produce a legal value. 
///  
public sealed class PriorityBindingExpression : BindingExpressionBase
{ 

    //-----------------------------------------------------
    //
    //  Constructors 
    //
    //----------------------------------------------------- 
 
    private PriorityBindingExpression(PriorityBinding binding, BindingExpressionBase owner)
        : base(binding, owner) 
    {
    }

    //------------------------------------------------------ 
    //
    //  Public Properties 
    // 
    //-----------------------------------------------------
 
    ///  Binding from which this expression was created 
    public PriorityBinding ParentPriorityBinding { get { return (PriorityBinding)ParentBindingBase; } }

    ///  List of inner BindingExpression  
    public ReadOnlyCollection   BindingExpressions
    { 
        get { return new ReadOnlyCollection(MutableBindingExpressions); } 
    }
 
    ///  Returns the active BindingExpression (or null) 
    public BindingExpressionBase ActiveBindingExpression
    {
        get { return (_activeIndex < 0) ? null : MutableBindingExpressions[_activeIndex]; } 
    }
 
    //------------------------------------------------------ 
    //
    //  Public Methods 
    //
    //------------------------------------------------------

    ///  Force a data transfer from source to target  
    public override void UpdateTarget()
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            bindExpr.UpdateTarget();
        }
    }
 
    ///  Send the current value back to the source 
    ///  Does nothing when binding's Mode is not TwoWay or OneWayToSource  
    public override void UpdateSource() 
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        {
            bindExpr.UpdateSource();
        } 
    }
 
#region Expression overrides 

    ///  
    ///     Called to evaluate the Expression value
    /// 
    /// DependencyObject being queried
    /// Property being queried 
    /// Computed value. Unset if unavailable.
    internal override object GetValue(DependencyObject d, DependencyProperty dp) 
    { 
        return Value;
    } 

    /// 
    ///     Allows Expression to store set values
    ///  
    /// DependencyObject being set
    /// Property being set 
    /// Value being set 
    /// true if Expression handled storing of the value
    internal override bool SetValue(DependencyObject d, DependencyProperty dp, object value) 
    {
        bool result;
        BindingExpressionBase bindExpr = ActiveBindingExpression;
 
        if (bindExpr != null)
        { 
            result = bindExpr.SetValue(d, dp, value); 
            if (result)
            { 
                // the active binding's value becomes the value of the priority binding
                Value = bindExpr.Value;
            }
        } 
        else
        { 
            // If we couldn't find the active binding, just return true to keep the property 
            // engine from removing the PriorityBinding.
            result = true; 
        }

        return result;
    } 

#endregion  Expression overrides 
 
    //-----------------------------------------------------
    // 
    //  Internal Methods
    //
    //------------------------------------------------------
 
    // Create a new BindingExpression from the given Binding description
    internal static PriorityBindingExpression CreateBindingExpression(DependencyObject d, DependencyProperty dp, PriorityBinding binding, BindingExpressionBase owner) 
    { 
        FrameworkPropertyMetadata fwMetaData = dp.GetMetadata(d.DependencyObjectType) as FrameworkPropertyMetadata;
 
        if ((fwMetaData != null && !fwMetaData.IsDataBindingAllowed) || dp.ReadOnly)
            throw new ArgumentException(SR.Get(SRID.PropertyNotBindable, dp.Name), "dp");

        // create the BindingExpression 
        PriorityBindingExpression bindExpr = new PriorityBindingExpression(binding, owner);
 
        return bindExpr; 
    }
 
    //-----------------------------------------------------
    //
    //  Protected Internal Properties
    // 
    //-----------------------------------------------------
 
    ///  
    ///     Number of BindingExpressions that have been attached and are listening
    ///  
    internal int AttentiveBindingExpressions
    {
        get { return (_activeIndex == NoActiveBindingExpressions) ? MutableBindingExpressions.Count : _activeIndex + 1; }
    } 

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

    /// 
    ///     Attach a BindingExpression to the given target (element, property) 
    /// 
    /// DependencyObject being set 
    /// Property being set 
    internal override bool AttachOverride(DependencyObject d, DependencyProperty dp)
    { 
        if (!base.AttachOverride(d, dp))
            return false;

        DependencyObject target = TargetElement; 
        if (target == null)
            return false; 
 
        SetStatus(BindingStatus.Active);
 
        int count = ParentPriorityBinding.Bindings.Count;
        _activeIndex = NoActiveBindingExpressions;
        Debug.Assert(MutableBindingExpressions.Count == 0, "expect to encounter empty BindingExpression collection when attaching MultiBinding");
        for (int i = 0; i < count; ++i) 
        {
            AttachBindingExpression(i, false);   // create new binding and have it added to end 
        } 

        return true; 
    }

    ///  sever all connections 
    internal override void DetachOverride() 
    {
        // Theoretically, we only need to detach number of AttentiveBindings, 
        // but we'll traverse the whole list anyway and do aggressive clean-up. 
        int count = MutableBindingExpressions.Count;
        for (int i = 0; i < count; ++i) 
        {
            BindingExpressionBase b = MutableBindingExpressions[i];
            if (b != null)
                b.Detach(); 
        }
 
        ChangeSources(null); 

        base.DetachOverride(); 
    }

    /// 
    /// Invalidate the given child expression. 
    /// 
    internal override void InvalidateChild(BindingExpressionBase bindingExpression) 
    { 
        // Prevent re-entrancy, because ChooseActiveBindingExpression() may
        // activate/deactivate a BindingExpression that indirectly calls this again. 
        if (_isInInvalidateBinding)
            return;
        _isInInvalidateBinding = true;
 
        int index = MutableBindingExpressions.IndexOf(bindingExpression);
        DependencyObject target = TargetElement; 
 
        if (target != null && 0 <= index && index < AttentiveBindingExpressions)
        { 
            // Optimization: only look for new ActiveBindingExpression when necessary:
            // 1. it is a higher priority BindingExpression (or there's no ActiveBindingExpression), or
            // 2. the existing ActiveBindingExpression is broken
            if (    index != _activeIndex 
                ||  (bindingExpression.Status != BindingStatus.Active && !bindingExpression.UsingFallbackValue))
            { 
                ChooseActiveBindingExpression(target); 
            }
 
            // update the value
            UsingFallbackValue = false;
            BindingExpressionBase bindExpr = ActiveBindingExpression;
            object newValue = (bindExpr != null) ? bindExpr.GetValue(target, TargetProperty) : UseFallbackValue(); 
            ChangeValue(newValue, true);
 
            if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Transfer)) 
            {
                TraceData.Trace(TraceEventType.Warning, 
                                    TraceData.PriorityTransfer(
                                        TraceData.Identify(this),
                                        TraceData.Identify(newValue),
                                        _activeIndex, 
                                        TraceData.Identify(bindExpr)));
            } 
 
            // don't invalidate during Attach.  The property engine does it
            // already, and it would interfere with the on-demand activation 
            // of style-defined BindingExpressions.
            if (!IsAttaching)
            {
                // recompute expression 
                target.InvalidateProperty(TargetProperty);
            } 
        } 

        _isInInvalidateBinding = false; 
    }

    /// 
    /// Change the dependency sources for the given child expression. 
    /// 
    internal override void ChangeSourcesForChild(BindingExpressionBase bindingExpression, WeakDependencySource[] newSources) 
    { 
        int index = MutableBindingExpressions.IndexOf(bindingExpression);
 
        if (index >= 0)
        {
            WeakDependencySource[] combinedSources = CombineSources(index, MutableBindingExpressions, AttentiveBindingExpressions, newSources);
            ChangeSources(combinedSources); 
        }
    } 
 
    /// 
    /// Replace the given child expression with a new one. 
    /// 
    internal override void ReplaceChild(BindingExpressionBase bindingExpression)
    {
        int index = MutableBindingExpressions.IndexOf(bindingExpression); 
        DependencyObject target = TargetElement;
 
        if (index >= 0 && target != null) 
        {
            // clean up the old BindingExpression 
            bindingExpression.Detach();

            // create a replacement BindingExpression and put it in the collection
            bindingExpression = AttachBindingExpression(index, true); 
        }
    } 
 
    // register the leaf bindings with the binding group
    internal override void UpdateBindingGroup(BindingGroup bg) 
    {
        for (int i=0, n=MutableBindingExpressions.Count-1; i
    /// Get the raw proposed value 
    /// 
    internal override object GetRawProposedValue()
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            return bindExpr.GetRawProposedValue(); 
        }
        return DependencyProperty.UnsetValue; 
    }

    /// 
    /// Get the converted proposed value 
    /// 
    internal override object ConvertProposedValue(object rawValue) 
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ConvertProposedValue(rawValue);
        }
        return DependencyProperty.UnsetValue; 
    }
 
    ///  
    /// Get the converted proposed value and inform the binding group
    ///  
    internal override bool ObtainConvertedProposedValue(BindingGroup bindingGroup)
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ObtainConvertedProposedValue(bindingGroup); 
        } 

        return true; 
    }

    /// 
    /// Update the source value 
    /// 
    internal override object UpdateSource(object convertedValue) 
    { 
        object result;
        BindingExpressionBase bindExpr = ActiveBindingExpression; 

        if (bindExpr != null)
        {
            result = bindExpr.UpdateSource(convertedValue); 

            if (bindExpr.Status == BindingStatus.UpdateSourceError) 
            { 
                SetStatus(BindingStatus.UpdateSourceError);
            } 
        }
        else
        {
            result = DependencyProperty.UnsetValue; 
        }
 
        return result; 
    }
 
    /// 
    /// Update the source value and inform the binding group
    /// 
    internal override bool UpdateSource(BindingGroup bindingGroup) 
    {
        bool result = true; 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            result = bindExpr.UpdateSource(bindingGroup);

            if (bindExpr.Status == BindingStatus.UpdateSourceError)
            { 
                SetStatus(BindingStatus.UpdateSourceError);
            } 
        } 
        return result;
    } 

    /// 
    /// Store the value in the binding group
    ///  
    internal override void StoreValueInBindingGroup(object value, BindingGroup bindingGroup)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null)
        { 
            bindExpr.StoreValueInBindingGroup(value, bindingGroup);
        }
    }
 
    /// 
    /// Run validation rules for the given step 
    ///  
    internal override bool Validate(object value, ValidationStep validationStep)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null)
        {
            return bindExpr.Validate(value, validationStep); 
        }
        return true; 
    } 

    ///  
    /// Run validation rules for the given step, and inform the binding group
    /// 
    internal override bool CheckValidationRules(BindingGroup bindingGroup, ValidationStep validationStep)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        { 
            return bindExpr.CheckValidationRules(bindingGroup, validationStep);
        } 
        return true;
    }

    ///  
    /// Get the proposed value(s) that would be written to the source(s), applying
    /// conversion and checking UI-side validation rules. 
    ///  
    internal override bool ValidateAndConvertProposedValue(out Collection values)
    { 
        Debug.Assert(NeedsValidation, "check NeedsValidation before calling this");

        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            return bindExpr.ValidateAndConvertProposedValue(out values); 
        } 

        values = null; 
        return true;
    }

    //----------------------------------------------------- 
    //
    //  Private Properties 
    // 
    //------------------------------------------------------
 
    /// 
    /// expose a mutable version of the list of all BindingExpressions;
    /// derived internal classes need to be able to populate this list
    ///  
    private Collection MutableBindingExpressions
    { 
        get { return _list; } 
    }
 
    //------------------------------------------------------
    //
    //  Private Methods
    // 
    //-----------------------------------------------------
 
 
    // Create a BindingExpression for position i
    BindingExpressionBase AttachBindingExpression(int i, bool replaceExisting) 
    {
        DependencyObject target = TargetElement;
        if (target == null)
            return null; 

        BindingBase binding = ParentPriorityBinding.Bindings[i]; 
 
        BindingExpressionBase bindExpr = binding.CreateBindingExpression(target, TargetProperty, this);
        if (replaceExisting) // replace exisiting or add as new binding? 
            MutableBindingExpressions[i] = bindExpr;
        else
            MutableBindingExpressions.Add(bindExpr);
 
        bindExpr.Attach(target, TargetProperty);
        return bindExpr; 
    } 

    // Re-evaluate the choice of active BindingExpression 
    void ChooseActiveBindingExpression(DependencyObject target)
    {
        int i, count = MutableBindingExpressions.Count;
        for (i = 0; i < count; ++i) 
        {
            BindingExpressionBase bindExpr = MutableBindingExpressions[i]; 
 
            // Try to activate the BindingExpression if it isn't already activate
            if (bindExpr.Status == BindingStatus.Inactive) 
                bindExpr.Activate();

            if (bindExpr.Status == BindingStatus.Active || bindExpr.UsingFallbackValue)
                break; 
        }
 
        int newActiveIndex = (i < count) ? i : NoActiveBindingExpressions; 

        // if active changes, tell the property engine the new list of sources 
        if (newActiveIndex != _activeIndex)
        {
            int oldActiveIndex = _activeIndex;
 
            // get new list of sources
            _activeIndex = newActiveIndex; 
            WeakDependencySource[] newSources = CombineSources(-1, MutableBindingExpressions, AttentiveBindingExpressions, null); 

            // tell property engine 
            ChangeSources(newSources);

            // deactivate BindingExpressions that don't need to be attentive
            // 
            if (newActiveIndex != NoActiveBindingExpressions)
                for (i = oldActiveIndex; i > newActiveIndex; --i) 
                    MutableBindingExpressions[i].Deactivate(); 
        }
    } 

    private void ChangeValue()
    {
    } 

    internal override void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args) 
    { 
        DependencyProperty dp = args.Property;
        int n = AttentiveBindingExpressions; 

        if (TraceData.IsExtendedTraceEnabled(this, TraceDataLevel.Events))
        {
            TraceData.Trace(TraceEventType.Warning, 
                                TraceData.GotPropertyChanged(
                                    TraceData.Identify(this), 
                                    TraceData.Identify(d), 
                                    dp.Name));
        } 

        for (int i=0; i  _list = new Collection(); 
    int         _activeIndex            = UnknownActiveBindingExpression;
    bool        _isInInvalidateBinding  = false; 
} 

} 

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