PriorityBindingExpression.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Framework / System / Windows / Data / PriorityBindingExpression.cs / 1 / 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 
    //
    //------------------------------------------------------

#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) 
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
            return bindExpr.SetValue(d, dp, value);

        // If we couldn't find the active binding, just return true to keep the property
        // engine from removing the PriorityBinding. 
        return true;
    } 
 
    /// 
    ///     Notification that a Dependent that this Expression established has 
    ///     been invalidated as a result of a Source invalidation
    /// 
    /// DependencyObject that was invalidated
    /// Changed event args for the property that was invalidated 
    internal override void OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
    { 
        // If this method is changed to use d or dp directly, uncomment these lines 
        //if (d == null)
        //    throw new ArgumentNullException(d); 
        //if (dp == null)
        //    throw new ArgumentNullException(dp);

        // if the notification arrived on the right Dispatcher, handle it now. 
        if (Dispatcher.Thread == Thread.CurrentThread)
        { 
            HandlePropertyInvalidation(d, args); 
        }
        else    // Otherwise, marshal it to the right Dispatcher. 
        {
            Dispatcher.BeginInvoke(
                DispatcherPriority.DataBind,
                new DispatcherOperationCallback(HandlePropertyInvalidationOperation), 
                new object[]{d, args});
        } 
    } 

#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 void AttachOverride(DependencyObject d, DependencyProperty dp)
    {
        base.AttachOverride(d, dp); 

        DependencyObject target = TargetElement; 
        if (target == null) 
            return;
 
        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
        } 
    }

    ///  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 void ObtainConvertedProposedValue(BindingGroup bindingGroup)
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            bindExpr.ObtainConvertedProposedValue(bindingGroup); 
        } 
    }
 
    /// 
    /// Update the source value and inform the binding group
    /// 
    internal override object UpdateSource(object convertedValue) 
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null) 
        {
            return bindExpr.UpdateSource(convertedValue); 
        }
        return DependencyProperty.UnsetValue;
    }
 
    /// 
    /// Update the source value and inform the binding group 
    ///  
    internal override void UpdateSource(BindingGroup bindingGroup)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null)
        {
            bindExpr.UpdateSource(bindingGroup); 
        }
    } 
 
    /// 
    /// 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; 
    }
 
    //-----------------------------------------------------
    //
    //  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()
    { 
    }

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

    private void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args) 
    { 
        DependencyProperty dp = args.Property;
        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 
    //
    //------------------------------------------------------

#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) 
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
            return bindExpr.SetValue(d, dp, value);

        // If we couldn't find the active binding, just return true to keep the property
        // engine from removing the PriorityBinding. 
        return true;
    } 
 
    /// 
    ///     Notification that a Dependent that this Expression established has 
    ///     been invalidated as a result of a Source invalidation
    /// 
    /// DependencyObject that was invalidated
    /// Changed event args for the property that was invalidated 
    internal override void OnPropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args)
    { 
        // If this method is changed to use d or dp directly, uncomment these lines 
        //if (d == null)
        //    throw new ArgumentNullException(d); 
        //if (dp == null)
        //    throw new ArgumentNullException(dp);

        // if the notification arrived on the right Dispatcher, handle it now. 
        if (Dispatcher.Thread == Thread.CurrentThread)
        { 
            HandlePropertyInvalidation(d, args); 
        }
        else    // Otherwise, marshal it to the right Dispatcher. 
        {
            Dispatcher.BeginInvoke(
                DispatcherPriority.DataBind,
                new DispatcherOperationCallback(HandlePropertyInvalidationOperation), 
                new object[]{d, args});
        } 
    } 

#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 void AttachOverride(DependencyObject d, DependencyProperty dp)
    {
        base.AttachOverride(d, dp); 

        DependencyObject target = TargetElement; 
        if (target == null) 
            return;
 
        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
        } 
    }

    ///  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 void ObtainConvertedProposedValue(BindingGroup bindingGroup)
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null) 
        {
            bindExpr.ObtainConvertedProposedValue(bindingGroup); 
        } 
    }
 
    /// 
    /// Update the source value and inform the binding group
    /// 
    internal override object UpdateSource(object convertedValue) 
    {
        BindingExpressionBase bindExpr = ActiveBindingExpression; 
        if (bindExpr != null) 
        {
            return bindExpr.UpdateSource(convertedValue); 
        }
        return DependencyProperty.UnsetValue;
    }
 
    /// 
    /// Update the source value and inform the binding group 
    ///  
    internal override void UpdateSource(BindingGroup bindingGroup)
    { 
        BindingExpressionBase bindExpr = ActiveBindingExpression;
        if (bindExpr != null)
        {
            bindExpr.UpdateSource(bindingGroup); 
        }
    } 
 
    /// 
    /// 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; 
    }
 
    //-----------------------------------------------------
    //
    //  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()
    { 
    }

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

    private void HandlePropertyInvalidation(DependencyObject d, DependencyPropertyChangedEventArgs args) 
    { 
        DependencyProperty dp = args.Property;
        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