Binding.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Framework / System / Windows / Data / Binding.cs / 5 / Binding.cs

                            //---------------------------------------------------------------------------- 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
// Description: Defines Binding object, which describes an instance of data Binding. 
// 
// See spec at [....]/connecteddata/Specs/Data%20Binding.mht
// 
//---------------------------------------------------------------------------

using System;
using System.Collections.Generic; 
using System.Collections.ObjectModel;
using System.Globalization; 
using System.Diagnostics; 
using System.ComponentModel;
using System.Xml; 

using System.Windows;
using System.Windows.Controls;  // Validation
using System.Windows.Markup; 
using MS.Utility;
using MS.Internal; // Invariant.Assert 
using MS.Internal.Controls; // Validation 
using MS.Internal.Data;
using MS.Internal.KnownBoxes; 

namespace System.Windows.Data
{
 
    /// 
    /// Status of the Binding 
    ///  
    public enum BindingStatus
    { 
        ///  Binding has not yet been attached to its target 
        Unattached = 0,
        ///  Binding has not yet been activated 
        Inactive, 
        ///  Binding has been successfully activated 
        Active, 
        ///  Binding has been detached from its target  
        Detached,
        ///  Binding is waiting for an async operation to complete 
        AsyncRequestPending,
        ///  error - source path could not be resolved 
        PathError,
        ///  error - a legal value could not be obtained from the source 
        UpdateTargetError,
        ///  error - the value could not be sent to the source  
        UpdateSourceError, 
    }
 
    /// 
    ///  Describes an instance of a Binding, binding a target
    ///  (DependencyObject, DependencyProperty) to a source (object, property)
    ///  
    public class Binding : BindingBase
    { 
        //----------------------------------------------------- 
        //
        //  Enums 
        //
        //-----------------------------------------------------

        // Which source property is in use 
        enum SourceProperties : byte { None, RelativeSource, ElementName, Source, InternalSource }
 
 
        //------------------------------------------------------
        // 
        //  Dynamic properties and events
        //
        //-----------------------------------------------------
 
        /// 
        /// The SourceUpdated event is raised whenever a value is transferred from the target to the source, 
        /// but only for Bindings that have requested the event by setting BindFlags.NotifyOnSourceUpdated. 
        /// 
        public static readonly RoutedEvent SourceUpdatedEvent = 
                EventManager.RegisterRoutedEvent("SourceUpdated",
                                        RoutingStrategy.Bubble,
                                        typeof(EventHandler),
                                        typeof(Binding)); 

        ///  
        ///     Adds a handler for the SourceUpdated attached event 
        /// 
        /// UIElement or ContentElement that listens to this event 
        /// Event Handler to be added
        public static void AddSourceUpdatedHandler(DependencyObject element, EventHandler handler)
        {
            FrameworkElement.AddHandler(element, SourceUpdatedEvent, handler); 
        }
 
        ///  
        ///     Removes a handler for the SourceUpdated attached event
        ///  
        /// UIElement or ContentElement that listens to this event
        /// Event Handler to be removed
        public static void RemoveSourceUpdatedHandler(DependencyObject element, EventHandler handler)
        { 
            FrameworkElement.RemoveHandler(element, SourceUpdatedEvent, handler);
        } 
 
        /// 
        /// The TargetUpdated event is raised whenever a value is transferred from the source to the target, 
        /// but only for Bindings that have requested the event by setting BindFlags.NotifyOnTargetUpdated.
        /// 
        public static readonly RoutedEvent TargetUpdatedEvent =
                EventManager.RegisterRoutedEvent("TargetUpdated", 
                                        RoutingStrategy.Bubble,
                                        typeof(EventHandler), 
                                        typeof(Binding)); 

        ///  
        ///     Adds a handler for the TargetUpdated attached event
        /// 
        /// UIElement or ContentElement that listens to this event
        /// Event Handler to be added 
        public static void AddTargetUpdatedHandler(DependencyObject element, EventHandler handler)
        { 
            FrameworkElement.AddHandler(element, TargetUpdatedEvent, handler); 
        }
 
        /// 
        ///     Removes a handler for the TargetUpdated attached event
        /// 
        /// UIElement or ContentElement that listens to this event 
        /// Event Handler to be removed
        public static void RemoveTargetUpdatedHandler(DependencyObject element, EventHandler handler) 
        { 
            FrameworkElement.RemoveHandler(element, TargetUpdatedEvent, handler);
        } 


        // 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 checks that the type of the DP agrees with the type of the static 
        // accessors.  But setting the type of the DP to XmlNamespaceManager would
        // JIT System.Xml during the static cctor, which is considered a perf bug. 
        // So instead we set the type of the DP to 'object' and use the
        // ValidateValueCallback to ensure that only values of the right type are allowed.
        // Meanwhile, disable the PreSharp warning
        #pragma warning disable 7008 

        ///  
        /// The XmlNamespaceManager to use to perform Namespace aware XPath queries in XmlData bindings 
        /// 
        public static readonly DependencyProperty XmlNamespaceManagerProperty= 
                DependencyProperty.RegisterAttached("XmlNamespaceManager", typeof(object), typeof(Binding),
                                            new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.Inherits),
                                            new ValidateValueCallback(IsValidXmlNamespaceManager));
 
        ///  Static accessor for XmlNamespaceManager property 
        ///  DependencyObject target cannot be null  
        public static XmlNamespaceManager GetXmlNamespaceManager(DependencyObject target) 
        {
            if (target == null) 
                throw new ArgumentNullException("target");

            return (XmlNamespaceManager)target.GetValue(XmlNamespaceManagerProperty);
        } 

        ///  Static modifier for XmlNamespaceManager property  
        ///  DependencyObject target cannot be null  
        public static void SetXmlNamespaceManager(DependencyObject target, XmlNamespaceManager value)
        { 
            if (target == null)
                throw new ArgumentNullException("target");

            target.SetValue(XmlNamespaceManagerProperty, value); 
        }
 
        private static bool IsValidXmlNamespaceManager(object value) 
        {
            return (value == null) || IsValidXmlNamespaceManagerHelper(value); 
        }

        // this is a separate function to avoid JIT of System.Xml during static ctor.
        // Property registration calls the ValidateValue callback on the default value, 
        // i.e. IsValidXmlNamespaceManager(null).
        private static bool IsValidXmlNamespaceManagerHelper(object value) 
        { 
            return (value is XmlNamespaceManager);
        } 

        #pragma warning restore 7008
        #pragma warning restore 1634, 1691
 

        //------------------------------------------------------ 
        // 
        //  Constructors
        // 
        //------------------------------------------------------

        /// 
        /// Default constructor. 
        /// 
        public Binding() {} 
 
        /// 
        /// Convenience constructor.  Sets most fields to default values. 
        /// 
        /// source path 
        public Binding(string path)
        { 
            if (path != null)
            { 
                if (System.Windows.Threading.Dispatcher.CurrentDispatcher == null) 
                    throw new InvalidOperationException();  // This is actually never called since CurrentDispatcher will throw if null.
 
                _ppath = new PropertyPath(path);
                _attachedPropertiesInPath = -1;
            }
        } 

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

        /// 
        ///     Collection<ValidationRule> is a collection of ValidationRule 
        ///     implementations on either a Binding or a MultiBinding.  Each of the rules
        ///     is run by the binding engine when validation on update to source 
        ///  
        public Collection ValidationRules
        { 
            get
            {
                if (_validationRules == null)
                    _validationRules = new ValidationRuleCollection(); 

                return _validationRules; 
            } 

        } 

        /// 
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized. 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeValidationRules() 
        {
            return (_validationRules != null && _validationRules.Count > 0); 
        }

        ///  True if an exception during source updates should be considered a validation error.
        [DefaultValue(false)] 
        public bool ValidatesOnExceptions
        { 
            get 
            {
                return TestFlag(BindingFlags.ValidatesOnExceptions); 
            }
            set
            {
                bool currentValue = TestFlag(BindingFlags.ValidatesOnExceptions); 
                if (currentValue != value)
                { 
                    CheckSealed(); 
                    ChangeFlag(BindingFlags.ValidatesOnExceptions, value);
                } 
            }
        }

        ///  True if a data error in the source item should be considered a validation error. 
        [DefaultValue(false)]
        public bool ValidatesOnDataErrors 
        { 
            get
            { 
                return TestFlag(BindingFlags.ValidatesOnDataErrors);
            }
            set
            { 
                bool currentValue = TestFlag(BindingFlags.ValidatesOnDataErrors);
                if (currentValue != value) 
                { 
                    CheckSealed();
                    ChangeFlag(BindingFlags.ValidatesOnDataErrors, value); 
                }
            }
        }
 

        ///  The source path (for CLR bindings). 
        public PropertyPath Path 
        {
            get { return _ppath; } 
            set
            {
                CheckSealed();
 
                _ppath = value;
                _attachedPropertiesInPath = -1; 
                ClearFlag(BindingFlags.PathGeneratedInternally); 
            }
        } 

        /// 
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized. 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializePath() 
        {
            return _ppath != null && !TestFlag(BindingFlags.PathGeneratedInternally); 
        }

        ///  The XPath path (for XML bindings).
        [DefaultValue(null)] 
        public string XPath
        { 
            get { return _xpath; } 
            set
            { 
                CheckSealed();

                _xpath = value;
            } 
        }
 
        ///  Binding mode  
        [DefaultValue(BindingMode.Default)]
        public BindingMode Mode 
        {
            get
            {
                switch (GetFlagsWithinMask(BindingFlags.PropagationMask)) 
                {
                    case BindingFlags.OneWay:           return BindingMode.OneWay; 
                    case BindingFlags.TwoWay:           return BindingMode.TwoWay; 
                    case BindingFlags.OneWayToSource:   return BindingMode.OneWayToSource;
                    case BindingFlags.OneTime:          return BindingMode.OneTime; 
                    case BindingFlags.PropDefault:      return BindingMode.Default;
                }
                Invariant.Assert(false, "Unexpected BindingMode value");
                return 0; 
            }
            set 
            { 
                CheckSealed();
 
                BindingFlags flags = FlagsFrom(value);
                if (flags == BindingFlags.IllegalInput)
                    throw new InvalidEnumArgumentException("value", (int) value, typeof(BindingMode));
 
                ChangeFlagsWithinMask(BindingFlags.PropagationMask, flags);
            } 
        } 

        ///  Update type  
        [DefaultValue(UpdateSourceTrigger.Default)]
        public UpdateSourceTrigger UpdateSourceTrigger
        {
            get 
            {
                switch (GetFlagsWithinMask(BindingFlags.UpdateMask)) 
                { 
                    case BindingFlags.UpdateOnPropertyChanged: return UpdateSourceTrigger.PropertyChanged;
                    case BindingFlags.UpdateOnLostFocus:    return UpdateSourceTrigger.LostFocus; 
                    case BindingFlags.UpdateExplicitly:     return UpdateSourceTrigger.Explicit;
                    case BindingFlags.UpdateDefault:        return UpdateSourceTrigger.Default;
                }
                Invariant.Assert(false, "Unexpected UpdateSourceTrigger value"); 
                return 0;
            } 
            set 
            {
                CheckSealed(); 

                BindingFlags flags = FlagsFrom(value);
                if (flags == BindingFlags.IllegalInput)
                    throw new InvalidEnumArgumentException("value", (int) value, typeof(UpdateSourceTrigger)); 

                ChangeFlagsWithinMask(BindingFlags.UpdateMask, flags); 
            } 
        }
 
        ///  Raise SourceUpdated event whenever a value flows from target to source 
        [DefaultValue(false)]
        public bool NotifyOnSourceUpdated
        { 
            get
            { 
                return TestFlag(BindingFlags.NotifyOnSourceUpdated); 
            }
            set 
            {
                bool currentValue = TestFlag(BindingFlags.NotifyOnSourceUpdated);
                if (currentValue != value)
                { 
                    CheckSealed();
                    ChangeFlag(BindingFlags.NotifyOnSourceUpdated, value); 
                } 
            }
        } 


        ///  Raise TargetUpdated event whenever a value flows from source to target 
        [DefaultValue(false)] 
        public bool NotifyOnTargetUpdated
        { 
            get 
            {
                return TestFlag(BindingFlags.NotifyOnTargetUpdated); 
            }
            set
            {
                bool currentValue = TestFlag(BindingFlags.NotifyOnTargetUpdated); 
                if (currentValue != value)
                { 
                    CheckSealed(); 
                    ChangeFlag(BindingFlags.NotifyOnTargetUpdated, value);
                } 
            }
        }

        ///  Raise ValidationError event whenever there is a ValidationError on Update 
        [DefaultValue(false)]
        public bool NotifyOnValidationError 
        { 
            get
            { 
                return TestFlag(BindingFlags.NotifyOnValidationError);
            }
            set
            { 
                bool currentValue = TestFlag(BindingFlags.NotifyOnValidationError);
                if (currentValue != value) 
                { 
                    CheckSealed();
                    ChangeFlag(BindingFlags.NotifyOnValidationError, value); 
                }
            }
        }
 
        ///  The Converter to apply 
        [DefaultValue(null)] 
        public IValueConverter Converter 
        {
            get { return _converter; } 
            set { CheckSealed();  _converter = value; }
        }

        ///  
        /// The parameter to pass to converter.
        ///  
        ///  
        [DefaultValue(null)]
        public object ConverterParameter 
        {
            get { return _converterParameter; }
            set { CheckSealed();  _converterParameter = value; }
        } 

        ///  Culture in which to evaluate the converter  
        [DefaultValue(null)] 
        [TypeConverter(typeof(System.Windows.CultureInfoIetfLanguageTagConverter))]
        public CultureInfo ConverterCulture 
        {
            get { return _culture; }
            set { CheckSealed();  _culture = value; }
        } 

        ///  object to use as the source  
        ///  To clear this property, set it to DependencyProperty.UnsetValue.  
        public object Source
        { 
            get
            {
                if (_objectSource == null)
                    return null; 
                return _objectSource.Target;
            } 
            set 
            {
                CheckSealed(); 

                if (_sourceInUse == SourceProperties.None || _sourceInUse == SourceProperties.Source)
                {
                    if (value != DependencyProperty.UnsetValue) 
                    {
                        _objectSource = new WeakReference(value); 
                        SourceReference = new ExplicitObjectRef(value); 
                    }
                    else 
                    {
                        _objectSource = null;
                        SourceReference = null;
                    } 
                }
                else 
                    throw new InvalidOperationException(SR.Get(SRID.BindingConflict, SourceProperties.Source, _sourceInUse)); 
            }
        } 

        /// 
        /// This method is used by TypeDescriptor to determine if this property should
        /// be serialized. 
        /// 
        [EditorBrowsable(EditorBrowsableState.Never)] 
        public bool ShouldSerializeSource() 
        {
            //return _objectSource.IsAlive && _objectSource.Target != DependencyProperty.UnsetValue; 

            // M8.2: always false
            return false;
        } 

        ///  
        /// Description of the object to use as the source, relative to the target element. 
        /// 
        [DefaultValue(null)] 
        public RelativeSource RelativeSource
        {
            get { return _relativeSource; }
            set 
            {
                CheckSealed(); 
 
                if (_sourceInUse == SourceProperties.None || _sourceInUse == SourceProperties.RelativeSource)
                { 
                    _relativeSource = value;
                    SourceReference = (value != null) ? new RelativeObjectRef(value) : null;
                }
                else 
                    throw new InvalidOperationException(SR.Get(SRID.BindingConflict, SourceProperties.RelativeSource, _sourceInUse));
            } 
        } 

        ///  Name of the element to use as the source  
        [DefaultValue(null)]
        public string ElementName
        {
            get { return _elementSource; } 
            set
            { 
                CheckSealed(); 

                if (_sourceInUse == SourceProperties.None || _sourceInUse == SourceProperties.ElementName) 
                {
                    _elementSource = value;
                    SourceReference = (value != null) ? new ElementObjectRef(value) : null;
                } 
                else
                    throw new InvalidOperationException(SR.Get(SRID.BindingConflict, SourceProperties.ElementName, _sourceInUse)); 
            } 
        }
 
        ///  True if Binding should get/set values asynchronously 
        [DefaultValue(false)]
        public bool IsAsync
        { 
            get { return _isAsync; }
            set { CheckSealed();  _isAsync = value; } 
        } 

        ///  Opaque data passed to the asynchronous data dispatcher  
        [DefaultValue(null)]
        public object AsyncState
        {
            get { return _asyncState; } 
            set { CheckSealed();  _asyncState = value; }
        } 
 
        ///  True if Binding should interpret its path relative to
        /// the data item itself. 
        /// 
        /// 
        /// The normal behavior (when this property is false)
        /// includes special treatment for a data item that implements IDataSource. 
        /// In this case, the path is treated relative to the object obtained
        /// from the IDataSource.Data property.  In addition, the binding listens 
        /// for the IDataSource.DataChanged event and reacts accordingly. 
        /// Setting this property to true overrides this behavior and gives
        /// the binding access to properties on the data source object itself. 
        /// 
        [DefaultValue(false)]
        public bool BindsDirectlyToSource
        { 
            get { return _bindsDirectlyToSource; }
            set { CheckSealed();  _bindsDirectlyToSource = value; } 
        } 

        ///  
        /// called whenever any exception is encountered when trying to update
        /// the value to the source. The application author can provide its own
        /// handler for handling exceptions here. If the delegate returns
        ///     null - don't throw an error or provide a ValidationError. 
        ///     Exception - returns the exception itself, we will fire the exception using Async exception model.
        ///     ValidationError - it will set itself as the BindingInError and add it to the element's Validation errors. 
        ///  
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter 
        {
            get
            {
                return _exceptionFilterCallback; 
            }
 
            set 
            {
                _exceptionFilterCallback = value; 
            }
        }

        //----------------------------------------------------- 
        //
        //  Public Fields 
        // 
        //-----------------------------------------------------
 
        /// 
        ///     A source property or a converter can return Binding.DoNothing
        ///     to instruct the binding engine to do nothing (i.e. do not transfer
        ///     a value to the target, do not move to the next Binding in a 
        ///     PriorityBinding, do not use the fallback or default value).
        ///  
        public static readonly object DoNothing = new NamedObject("Binding.DoNothing"); 

        ///  
        ///     This string is used as the PropertyName of the
        ///     PropertyChangedEventArgs to indicate that an indexer property
        ///     has been changed.
        ///  
        public const string IndexerName = "Item[]";
 
        //----------------------------------------------------- 
        //
        //  Protected Methods 
        //
        //------------------------------------------------------

        ///  
        /// Create an appropriate expression for this Binding, to be attached
        /// to the given DependencyProperty on the given DependencyObject. 
        ///  
        internal override BindingExpressionBase CreateBindingExpressionOverride(DependencyObject target, DependencyProperty dp, BindingExpressionBase owner)
        { 
            return BindingExpression.CreateBindingExpression(target, dp, this, owner);
        }

        internal override ValidationRule LookupValidationRule(Type type) 
        {
            return LookupValidationRule(type, ValidationRulesInternal); 
        } 

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

        internal object DoFilterException(object bindExpr, Exception exception) 
        { 
            if (_exceptionFilterCallback != null)
                return _exceptionFilterCallback(bindExpr, exception); 

            return exception;
        }
 
        // called by BindingExpression when the Binding doesn't specify a path.
        // (Can't use Path setter, since that replaces the BindingExpression.) 
        internal void UsePath(PropertyPath path) 
        {
            _ppath = path; 
            SetFlag(BindingFlags.PathGeneratedInternally);
        }

 
        //------------------------------------------------------
        // 
        //  Internal Properties 
        //
        //----------------------------------------------------- 

        internal override CultureInfo ConverterCultureInternal
        {
            get { return ConverterCulture; } 
        }
 
        internal ObjectRef SourceReference 
        {
            get { return (_source == UnsetSource) ? null : _source; } 
            set { CheckSealed();  _source = value;  DetermineSource(); }
        }

        internal object WorkerData 
        {
            get { return _workerData; } 
            set { _workerData = value; } 
        }
 
        internal bool TreeContextIsRequired
        {
            get
            { 
                bool treeContextIsRequired;
 
                // attached properties in the property path (like "(DockPanel.Dock)") 
                // need inherited value of XmlAttributeProperties properties for namespaces,
                // unless the properties are pre-resolved by the parser 
                if (_attachedPropertiesInPath < 0)
                {
                    if (_ppath != null)
                    { 
                        _attachedPropertiesInPath = _ppath.ComputeUnresolvedAttachedPropertiesInPath();
                    } 
                    else 
                    {
                        _attachedPropertiesInPath = 0; 
                    }
                }
                treeContextIsRequired = (_attachedPropertiesInPath > 0);
 
                // namespace prefixes in the XPath need an XmlNamespaceManager
                if (!treeContextIsRequired && !String.IsNullOrEmpty(XPath) && XPath.IndexOf(':') >= 0) 
                { 
                    treeContextIsRequired = true;
                } 

                return treeContextIsRequired;
            }
        } 

        // same as the public ValidationRules property, but 
        // doesn't try to create an instance if there isn't one there 
        internal Collection ValidationRulesInternal
        { 
            get
            {
                return _validationRules;
            } 
        }
 
        // when the source property has its default value, this flag controls 
        // whether the binding transfers the value anyway, or simply "hides"
        // so that the property engine obtains the target value some other way. 
        internal bool TransfersDefaultValue
        {
            get { return !_doesNotTransferDefaultValue; }
            set { CheckSealed();  _doesNotTransferDefaultValue = !value; } 
        }
 
 
        //------------------------------------------------------
        // 
        //  Private Methods
        //
        //-----------------------------------------------------
 
        // determine the source property currently in use
        void DetermineSource() 
        { 
            _sourceInUse =
                (_source == UnsetSource)                ? SourceProperties.None : 
                (_relativeSource != null)               ? SourceProperties.RelativeSource :
                (_elementSource != null)                ? SourceProperties.ElementName :
                (_objectSource != null)                 ? SourceProperties.Source :
                                                          SourceProperties.InternalSource; 
        }
 
        //----------------------------------------------------- 
        //
        //  Private Fields 
        //
        //-----------------------------------------------------

        object              _workerData; 
        SourceProperties    _sourceInUse;
 
        PropertyPath        _ppath; 
        string              _xpath;
        ObjectRef           _source = UnsetSource; 
        CultureInfo         _culture;

        bool                _isAsync;
        object              _asyncState; 
        bool                _bindsDirectlyToSource;
        bool                _doesNotTransferDefaultValue;   // initially = false 
 
        WeakReference       _objectSource;
        RelativeSource      _relativeSource; 
        string              _elementSource;
        IValueConverter     _converter;
        object              _converterParameter;
 
        int                 _attachedPropertiesInPath;
        ValidationRuleCollection _validationRules; 
        UpdateSourceExceptionFilterCallback _exceptionFilterCallback; 

        static readonly ObjectRef UnsetSource = new ExplicitObjectRef(null); 
    }
}


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