ObjectRef.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Data / ObjectRef.cs / 1305600 / ObjectRef.cs

                             
//----------------------------------------------------------------------------
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved. 
// 
// 
// Description: ObjectRef is a general way to name objects used in data binding 
//
// See spec at http://avalon/connecteddata/Specs/Data%20Binding.mht 
//
//---------------------------------------------------------------------------

using System; 
using System.Collections;
using System.Diagnostics; 
using System.Globalization; 
using System.Reflection;
using System.Windows; 
using System.Windows.Media;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Markup; 
using MS.Internal;
using MS.Internal.Utility; 
 
namespace MS.Internal.Data
{ 
    #region ObjectRefArgs

    // args to GetObject and GetDataObject
    internal class ObjectRefArgs 
    {
        internal bool IsTracing { get; set; } 
        internal bool ResolveNamesInTemplate { get; set; } 
        internal bool NameResolvedInOuterScope { get; set; }
    } 

    #endregion ObjectRefArgs

#region ObjectRef 
    ///  Abstract object reference. 
    internal abstract class ObjectRef 
    { 
        //-----------------------------------------------------
        // 
        //  Constructors
        //
        //-----------------------------------------------------
 
        ///  Constructor is protected - you can only create subclasses. 
        protected ObjectRef() {} 
 
        //------------------------------------------------------
        // 
        //  Public Methods
        //
        //-----------------------------------------------------
 
        ///  Returns the referenced object. 
        /// Element defining context for the reference.  
        /// See ObjectRefArgs  
        internal virtual object GetObject(DependencyObject d, ObjectRefArgs args)
        { 
            return null;
        }

        ///  Returns the data object associated with the referenced object. 
        /// Often this is the same as the referenced object.
        ///  
        /// Element defining context for the reference.  
        /// See ObjectRefArgs 
        internal virtual object GetDataObject(DependencyObject d, ObjectRefArgs args) 
        {
            return GetObject(d, args);
        }
 
        ///  true if the ObjectRef really needs the tree context 
        internal bool TreeContextIsRequired(DependencyObject target) 
        { 
            return ProtectedTreeContextIsRequired(target);
        } 

        ///  true if the ObjectRef really needs the tree context 
        protected virtual bool ProtectedTreeContextIsRequired(DependencyObject target)
        { 
            return false;
        } 
 
        /// 
        /// true if the ObjectRef uses the mentor of the target element, 
        /// rather than the target element itself.
        /// 
        internal bool UsesMentor
        { 
            get { return ProtectedUsesMentor; }
        } 
 
        /// 
        /// true if the ObjectRef uses the mentor of the target element, 
        /// rather than the target element itself.
        /// 
        protected virtual bool ProtectedUsesMentor
        { 
            get { return true; }
        } 
 
        /// 
        /// identify this ObjectRef to the user - used by extended tracing 
        /// 
        internal abstract string Identify();
    }
 
#endregion ObjectRef
 
#region ElementObjectRef 
    ///  Object reference to a DependencyObject via its Name. 
    internal sealed class ElementObjectRef : ObjectRef 
    {
        //------------------------------------------------------
        //
        //  Constructors 
        //
        //------------------------------------------------------ 
 
        ///  Constructor. 
        /// Name of the referenced Element. 
        ///  name is a null reference 
        internal ElementObjectRef(string name)
        {
            if (name == null) 
                throw new ArgumentNullException("name");
 
            _name = name.Trim(); 
        }
 
        //-----------------------------------------------------
        //
        //  Public Methods
        // 
        //------------------------------------------------------
 
        ///  Returns the referenced object.  
        /// Element defining context for the reference. 
        /// See ObjectRefArgs  
        internal override object GetObject(DependencyObject d, ObjectRefArgs args)
        {
            if (d == null)
                throw new ArgumentNullException("d"); 

            object o = null; 
            if (args.ResolveNamesInTemplate) 
            {
                // look in container's template (if any) first 
                FrameworkElement fe = d as FrameworkElement;
                if (fe != null && fe.TemplateInternal != null)
                {
                    o = Helper.FindNameInTemplate(_name, d); 

                    if (args.IsTracing) 
                    { 
                        TraceData.Trace(TraceEventType.Warning,
                                            TraceData.ElementNameQueryTemplate( 
                                                _name,
                                                TraceData.Identify(d)));
                    }
                } 

                if (o == null) 
                { 
                    args.NameResolvedInOuterScope = true;
                } 
            }

            FrameworkObject fo = new FrameworkObject(d);
            while (o == null && fo.DO != null) 
            {
                DependencyObject scopeOwner; 
                o = fo.FindName(_name, out scopeOwner); 

                // if the original element is a scope owner, supports IComponentConnector, 
                // and has a parent, don't use the result of FindName.  The
                // element is probably an instance of a Xaml-subclassed control;
                // we want to resolve the name starting in the next outer scope.
                // (bug 1669408) 
                // Also, if the element's NavigationService property is locally
                // set, the element is the root of a navigation and should use the 
                // inner scope (bug 1765041) 
                if (d == scopeOwner && d is IComponentConnector &&
                    d.ReadLocalValue(System.Windows.Navigation.NavigationService.NavigationServiceProperty) == DependencyProperty.UnsetValue) 
                {
                    DependencyObject parent = LogicalTreeHelper.GetParent(d);
                    if (parent == null)
                    { 
                        parent = Helper.FindMentor(d.InheritanceContext);
                    } 
 
                    if (parent != null)
                    { 
                        o = null;
                        fo.Reset(parent);
                        continue;
                    } 
                }
 
                if (args.IsTracing) 
                {
                    TraceData.Trace(TraceEventType.Warning, 
                                        TraceData.ElementNameQuery(
                                            _name,
                                            TraceData.Identify(fo.DO)));
                } 

                if (o == null) 
                { 
                    args.NameResolvedInOuterScope = true;
 
                    // move to the next outer namescope.
                    // First try TemplatedParent of the scope owner.
                    FrameworkObject foScopeOwner = new FrameworkObject(scopeOwner);
                    DependencyObject dd = foScopeOwner.TemplatedParent; 

                    // if that doesn't work, we could be at the top of 
                    // generated content for an ItemsControl.  If so, use 
                    // the (visual) parent - a panel.
                    if (dd == null) 
                    {
                        Panel panel = fo.FrameworkParent.DO as Panel;
                        if (panel != null && panel.IsItemsHost)
                        { 
                            dd = panel;
                        } 
                    } 

                    // next, see if we're in a logical tree attached directly 
                    // to a ContentPresenter.  This is the m---- equivalent of
                    // having the ContentPresenter as the TemplatedParent.
                    if (dd == null && scopeOwner == null)
                    { 
                        // go to the top of the logical subtree
                        DependencyObject parent; 
                        for (dd = fo.DO;;) 
                        {
                            parent = LogicalTreeHelper.GetParent(dd); 
                            if (parent == null)
                            {
                                parent = Helper.FindMentor(dd.InheritanceContext);
                            } 

                            if (parent == null) 
                                break; 

                            dd = parent; 
                        }

                        // if it's attached to a ContentPresenter, move to the CP
                        ContentPresenter cp = VisualTreeHelper.IsVisualType(dd) ? VisualTreeHelper.GetParent(dd) as ContentPresenter : null; 
                        dd = (cp != null && cp.TemplateInternal.CanBuildVisualTree) ? cp : null;
                    } 
 
                    fo.Reset(dd);
                } 
            }

            if (o == null)
            { 
                o = DependencyProperty.UnsetValue;
                args.NameResolvedInOuterScope = false; 
            } 

            return o; 
        }

        public override string ToString()
        { 
            return String.Format(CultureInfo.InvariantCulture,
                    "ElementName={0}", _name); 
        } 

        internal override string Identify() 
        {
            return "ElementName";
        }
 
        //-----------------------------------------------------
        // 
        //  Private Fields 
        //
        //----------------------------------------------------- 

        string _name;
    }
 
#endregion ElementObjectRef
 
#region RelativeObjectRef 
    ///  Object reference relative to the target element.
    ///  
    internal sealed class RelativeObjectRef : ObjectRef
    {
        //-----------------------------------------------------
        // 
        //  Constructors
        // 
        //------------------------------------------------------ 

        ///  Constructor.  
        /// RelativeSource. 
        ///  relativeSource is a null reference 
        internal RelativeObjectRef(RelativeSource relativeSource)
        { 
            if (relativeSource == null)
                throw new ArgumentNullException("relativeSource"); 
 
            _relativeSource = relativeSource;
        } 

        //-----------------------------------------------------
        //
        //  Public Methods 
        //
        //------------------------------------------------------ 
 
        public override string ToString()
        { 
            string s;
            switch (_relativeSource.Mode)
            {
                case RelativeSourceMode.FindAncestor: 
                    s = String.Format(CultureInfo.InvariantCulture,
                        "RelativeSource {0}, AncestorType='{1}', AncestorLevel='{2}'", 
                        _relativeSource.Mode, 
                        _relativeSource.AncestorType,
                        _relativeSource.AncestorLevel); 
                    break;
                default:
                    s = String.Format(CultureInfo.InvariantCulture,
                        "RelativeSource {0}", _relativeSource.Mode); 
                    break;
            } 
 
            return s;
        } 

        ///  Returns the referenced object. 
        /// Element defining context for the reference. 
        /// See ObjectRefArgs  
        ///  d is a null reference 
        internal override object GetObject(DependencyObject d, ObjectRefArgs args) 
        { 
            return GetDataObjectImpl(d, args);
        } 

        ///  Returns the data object associated with the referenced object.
        /// Often this is the same as the referenced object.
        ///  
        /// Element defining context for the reference. 
        /// See ObjectRefArgs  
        ///  d is a null reference  
        internal override object GetDataObject(DependencyObject d, ObjectRefArgs args)
        { 
            object o = GetDataObjectImpl(d, args);
            DependencyObject el = o as DependencyObject;

            if (el != null && ReturnsDataContext) 
            {
                // for generated wrappers, use the ItemForContainer property instead 
                // of DataContext, since it's always set by the generator 
                o = el.GetValue(ItemContainerGenerator.ItemForItemContainerProperty);
                if (o == null) 
                    o = el.GetValue(FrameworkElement.DataContextProperty);
            }

            return o; 
        }
 
        private object GetDataObjectImpl(DependencyObject d, ObjectRefArgs args) 
        {
            if (d == null) 
                return null;

            switch (_relativeSource.Mode)
            { 
                case RelativeSourceMode.Self:
                    break;              // nothing to do 
 
                case RelativeSourceMode.TemplatedParent:
                    d = Helper.GetTemplatedParent(d); 
                    break;

                case RelativeSourceMode.PreviousData:
                    return GetPreviousData(d); 

                case RelativeSourceMode.FindAncestor: 
                    d = FindAncestorOfType(_relativeSource.AncestorType, _relativeSource.AncestorLevel, d, args.IsTracing); 
                    if (d == null)
                    { 
                        return DependencyProperty.UnsetValue;   // we fell off the tree
                    }
                    break;
 
                default:
                    return null; 
            } 

            if (args.IsTracing) 
            {
                TraceData.Trace(TraceEventType.Warning,
                                    TraceData.RelativeSource(
                                        _relativeSource.Mode, 
                                        TraceData.Identify(d)));
            } 
 
            return d;
        } 

        internal bool ReturnsDataContext
        {
            get { return (_relativeSource.Mode == RelativeSourceMode.PreviousData); } 
        }
 
        ///  true if the ObjectRef really needs the tree context  
        protected override bool ProtectedTreeContextIsRequired(DependencyObject target)
        { 
            return  (   (_relativeSource.Mode == RelativeSourceMode.FindAncestor
                    ||  (_relativeSource.Mode == RelativeSourceMode.PreviousData)));
        }
 
        protected override bool ProtectedUsesMentor
        { 
            get 
            {
                switch (_relativeSource.Mode) 
                {
                    case RelativeSourceMode.TemplatedParent:
                    case RelativeSourceMode.PreviousData:
                        return true; 

                    default: 
                        return false; 
                }
            } 
        }

        internal override string Identify()
        { 
            return String.Format(System.Windows.Markup.TypeConverterHelper.InvariantEnglishUS,
                "RelativeSource ({0})", _relativeSource.Mode); 
        } 

        //------------------------------------------------------ 
        //
        //  Private Method
        //
        //----------------------------------------------------- 

        private object GetPreviousData(DependencyObject d) 
        { 
            // move up to the next containing DataContext scope
            for (; d != null; d = FrameworkElement.GetFrameworkParent(d)) 
            {
                if (BindingExpression.HasLocalDataContext(d))
                {
                    // special case:  if the element is a ContentPresenter 
                    // whose templated parent is a ContentControl or
                    // HeaderedItemsControl, and both have the same 
                    // DataContext, we'll use the parent instead of the 
                    // ContentPresenter.  In this case, the DataContext
                    // of the CP is set by various forwarding rules, and 
                    // shouldn't count as a new scope.
                    // Similarly, do the same for a FE whose parent
                    // is a GridViewRowPresenter;  this enables Previous bindings
                    // inside ListView. 
                    FrameworkElement parent, child;
                    ContentPresenter cp; 
 
                    if ((cp = d as ContentPresenter) != null)
                    { 
                        child = cp;
                        parent = cp.TemplatedParent as FrameworkElement;
                        if (!(parent is ContentControl || parent is HeaderedItemsControl))
                        { 
                            parent = cp.Parent as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
                        } 
                    } 
                    else
                    { 
                        child = d as FrameworkElement;
                        parent = ((child != null) ? child.Parent : null) as System.Windows.Controls.Primitives.GridViewRowPresenterBase;
                    }
 
                    if (child != null && parent != null &&
                        Object.Equals(child.DataContext, parent.DataContext)) 
                    { 
                        d = parent;
                        if (!BindingExpression.HasLocalDataContext(parent)) 
                        {
                            continue;
                        }
                    } 

                    break; 
                } 
            }
 
            if (d == null)
                return DependencyProperty.UnsetValue;   // we fell off the tree

            // this only makes sense within generated content.  If this 
            // is the case, then d is now the wrapper element, its visual
            // parent is the layout element, and the layout's ItemsOwner 
            // is the govening ItemsControl. 
            Visual v = d as Visual;
            DependencyObject layout = (v != null) ? VisualTreeHelper.GetParent(v) : null; 
            ItemsControl ic = ItemsControl.GetItemsOwner(layout);
            if (ic == null)
            {
                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.RefPreviousNotInContext);
                return null; 
            } 

            // now look up the wrapper's previous sibling within the 
            // layout's children collection
            Visual v2 = layout as Visual;
            int count = (v2 != null) ? v2.InternalVisualChildrenCount : 0;
            int j = -1; 
            Visual prevChild = null;   //child at j-1th index
            if (count != 0) 
            { 
                j = IndexOf(v2, v, out prevChild);
            } 
            if (j > 0)
            {
                d = prevChild;
            } 
            else
            { 
                d = null; 
                if ((j < 0) && TraceData.IsEnabled)
                    TraceData.Trace(TraceEventType.Error, TraceData.RefNoWrapperInChildren); 
            }
            return d;
        }
 
        private DependencyObject FindAncestorOfType(Type type, int level, DependencyObject d, bool isTracing)
        { 
            if (type == null) 
            {
                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorTypeNotSpecified);
                return null;
            }
            if (level < 1) 
            {
                if (TraceData.IsEnabled) 
                    TraceData.Trace(TraceEventType.Error, TraceData.RefAncestorLevelInvalid); 
                return null;
            } 

            // initialize search to start at the parent of the given DO
            FrameworkObject fo = new FrameworkObject(d);
            fo.Reset(fo.GetPreferVisualParent(true).DO); 

            while (fo.DO != null) 
            { 
                if (isTracing)
                { 
                    TraceData.Trace(TraceEventType.Warning,
                                        TraceData.AncestorLookup(
                                            type.Name,
                                            TraceData.Identify(fo.DO))); 
                }
 
                if (type.IsInstanceOfType(fo.DO))   // found it! 
                {
                    if (--level <= 0) 
                        break;
                }

                fo.Reset(fo.PreferVisualParent.DO); 
            }
 
            return fo.DO; 
        }
 
        private int IndexOf(Visual parent, Visual child, out Visual prevChild)
        {
            Visual temp;
            bool foundIndex = false; 
            prevChild = null;
            int count = parent.InternalVisualChildrenCount; 
            int i; 
            for(i = 0; i < count; i++)
            { 
                temp = parent.InternalGetVisualChild(i);
                if(child == temp)
                {
                    foundIndex = true; 
                    break;
                } 
                prevChild = temp; 
            }
            if (foundIndex) return i; 
            else return -1;
        }

        //------------------------------------------------------ 
        //
        //  Private Fields 
        // 
        //-----------------------------------------------------
 
        RelativeSource _relativeSource;
    }

#endregion RelativeObjectRef 

#region ExplicitObjectRef 
    ///  Explicit object reference.  
    internal sealed class ExplicitObjectRef: ObjectRef
    { 
        //-----------------------------------------------------
        //
        //  Constructors
        // 
        //-----------------------------------------------------
 
        ///  Constructor.  
        internal ExplicitObjectRef(object o)
        { 
            if (o is DependencyObject)
                _element = new WeakReference(o);
            else
                _object = o; 
        }
 
        //------------------------------------------------------ 
        //
        //  Public Methods 
        //
        //-----------------------------------------------------

        ///  Returns the referenced object.  
        /// Element defining context for the reference. 
        /// See ObjectRefArgs  
        internal override object GetObject(DependencyObject d, ObjectRefArgs args) 
        {
            return (_element != null) ? _element.Target : _object; 
        }

        /// 
        /// true if the ObjectRef uses the mentor of the target element, 
        /// rather than the target element itself.
        ///  
        protected override bool ProtectedUsesMentor 
        {
            get { return false; } 
        }

        internal override string Identify()
        { 
            return "Source";
        } 
 
        //------------------------------------------------------
        // 
        //  Private Fields
        //
        //------------------------------------------------------
 
        object _object;
        WeakReference _element; // to DependencyObject (bug 986435) 
    } 

#endregion ExplicitObjectRef 

}

 

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