UIElement.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 / Core / System / Windows / UIElement.cs / 9 / UIElement.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
//----------------------------------------------------------------------------- 
 
using MS.Utility;
using MS.Internal; 
using MS.Internal.Media;
using MS.Internal.PresentationCore;
using MS.Internal.KnownBoxes;
using System; 
using System.Collections;
using System.Collections.Generic; 
using System.Diagnostics; 
using System.ComponentModel;
using System.Security; 
using System.Security.Permissions;

using System.Windows.Automation.Peers;
 
using System.Windows.Input;
using System.Windows.Interop; 
using System.Windows.Media; 
using System.Windows.Media.Media3D;
using System.Windows.Media.Animation; 
using System.Windows.Media.Composition;
using System.Windows.Media.Effects;
using System.Windows.Markup;
using System.Windows.Threading; 
using System.Windows.Input.StylusPlugIns;
 
namespace System.Windows 
{
    ///  
    /// Visibility - Enum which describes 3 possible visibility options.
    /// 
    /// 
    public enum Visibility : byte 
    {
        ///  
        /// Normally visible. 
        /// 
        Visible = 0, 

        /// 
        /// Occupies space in the layout, but is not visible (completely transparent).
        ///  
        Hidden,
 
        ///  
        /// Not visible and does not occupy any space in layout, as if it doesn't exist.
        ///  
        Collapsed
    }

 
    /// 
    /// UIElement is the base class for frameworks building on the Windows Presentation Core. 
    ///  
    /// 
    /// UIElement adds to the base visual class "LIFE" - Layout, Input, Focus, and Eventing. 
    /// UIElement can be considered roughly equivalent to an HWND in Win32, or an Element in Trident.
    /// UIElements can render (because they derive from Visual), visually size and position their children,
    /// respond to user input (including control of where input is getting sent to),
    /// and raise events that traverse the physical tree. 
    ///
    /// UIElement is the most functional type in the Windows Presentation Core. 
    ///  

    public partial class UIElement : Visual, IInputElement, IAnimatable 
    {
        /// 
        ///  Critical: This code is used to register various thunks that are used to send input to the tree
        ///  TreatAsSafe: This code attaches handlers that are inside the class and private. Not configurable or overridable 
        /// 
        [SecurityCritical,SecurityTreatAsSafe] 
        static UIElement() 
        {
            RegisterEvents(); 

            RenderOptions.EdgeModeProperty.OverrideMetadata(
                typeof(UIElement),
                new UIPropertyMetadata(new PropertyChangedCallback(EdgeMode_Changed))); 

            RenderOptions.BitmapScalingModeProperty.OverrideMetadata( 
                typeof(UIElement), 
                new UIPropertyMetadata(new PropertyChangedCallback(BitmapScalingMode_Changed)));
 
        }

        /// 
        /// Constructor. This form of constructor will encounter a slight perf hit since it needs to initialize Dispatcher for the instance. 
        /// 
        public UIElement() 
        { 
            Initialize();
        } 

        private void Initialize()
        {
            BeginPropertyInitialization(); 
            NeverMeasured = true;
            NeverArranged = true; 
 
            SnapsToDevicePixelsCache = (bool) SnapsToDevicePixelsProperty.GetDefaultValue(DependencyObjectType);
            ClipToBoundsCache        = (bool) ClipToBoundsProperty.GetDefaultValue(DependencyObjectType); 
            VisibilityCache          = (Visibility) VisibilityProperty.GetDefaultValue(DependencyObjectType);

            SetFlags(true, VisualFlags.IsUIElement);
 
            // Note: IsVisibleCache is false by default.
        } 
 
        #region AllowDrop
 
        /// 
        ///     The DependencyProperty for the AllowDrop property.
        /// 
        public static readonly DependencyProperty AllowDropProperty = 
                    DependencyProperty.Register(
                                "AllowDrop", 
                                typeof(bool), 
                                typeof(UIElement),
                                new PropertyMetadata(BooleanBoxes.FalseBox)); 

        /// 
        ///     A dependency property that allows the drop object as DragDrop target.
        ///  
        public bool AllowDrop
        { 
            get { return (bool) GetValue(AllowDropProperty); } 
            set { SetValue(AllowDropProperty, BooleanBoxes.Box(value)); }
        } 

        #endregion AllowDrop

        ///  
        /// Get the StylusPlugInCollection associated with the UIElement
        ///  
        protected StylusPlugInCollection StylusPlugIns 
        {
            get 
            {
                StylusPlugInCollection stylusCollection = StylusPlugInsField.GetValue(this);
                if (stylusCollection == null)
                { 
                    stylusCollection = new StylusPlugInCollection(this);
                    StylusPlugInsField.SetValue(this, stylusCollection); 
                } 
                return stylusCollection;
            } 
        }

        /// 
        /// Returns the size the element computed during the Measure pass. 
        /// This is only valid if IsMeasureValid is true.
        ///  
        public Size DesiredSize 
        {
            get 
            {
                if(this.Visibility == Visibility.Collapsed)
                    return new Size(0,0);
                else 
                    return _desiredSize;
            } 
        } 

        internal Size PreviousConstraint 
        {
            get { return _previousAvailableSize; }
        }
 
        // This is needed to prevent dirty elements from drawing and crashing while doing so.
        private bool IsRenderable() 
        { 
            //elements that were created but never invalidated/measured are clean
            //from layout perspective, but we still don't want to render them 
            //because they don't have state build up enough for that.
            if(NeverMeasured || NeverArranged)
                return false;
 
            //if element is collapsed, no rendering is needed
            //it is not only perf optimization, but also protection from 
            //UIElement to break itself since RenderSize is reported as (0,0) 
            //when UIElement is Collapsed
            if(ReadFlag(CoreFlags.IsCollapsed)) 
                return false;

            return IsMeasureValid && IsArrangeValid;
        } 

        internal void InvalidateMeasureInternal() 
        { 
            MeasureDirty = true;
        } 

        internal void InvalidateArrangeInternal()
        {
            ArrangeDirty = true; 
        }
 
        ///  
        /// Determines if the DesiredSize is valid.
        ///  
        /// 
        /// A developer can force arrangement to be invalidated by calling InvalidateMeasure.
        /// IsArrangeValid and IsMeasureValid are related,
        /// in that arrangement cannot be valid without measurement first being valid. 
        /// 
        public bool IsMeasureValid 
        { 
            get { return !MeasureDirty; }
        } 

        /// 
        /// Determines if the RenderSize and position of child elements is valid.
        ///  
        /// 
        /// A developer can force arrangement to be invalidated by calling InvalidateArrange. 
        /// IsArrangeValid and IsMeasureValid are related, in that arrangement cannot be valid without measurement first 
        /// being valid.
        ///  
        public bool IsArrangeValid
        {
            get { return !ArrangeDirty; }
        } 

 
        ///  
        /// Invalidates the measurement state for the element.
        /// This has the effect of also invalidating the arrange state for the element. 
        /// The element will be queued for an update layout that will occur asynchronously.
        /// 
        public void InvalidateMeasure()
        { 
            if(     !MeasureDirty
                &&  !MeasureInProgress ) 
            { 
                Debug.Assert(MeasureRequest == null, "can't be clean and still have MeasureRequest");
 
//                 VerifyAccess();

                if(!NeverMeasured) //only measured once elements are allowed in *update* queue
                { 
                    ContextLayoutManager ContextLayoutManager = ContextLayoutManager.From(Dispatcher);
                    ContextLayoutManager.MeasureQueue.Add(this); 
                } 
                MeasureDirty = true;
            } 
        }

        /// 
        /// Invalidates the arrange state for the element. 
        /// The element will be queued for an update layout that will occur asynchronously.
        /// MeasureCore will not be called unless InvalidateMeasure is also called - or that something 
        /// else caused the measure state to be invalidated. 
        /// 
        public void InvalidateArrange() 
        {
            if(   !ArrangeDirty
               && !ArrangeInProgress)
            { 
                Debug.Assert(ArrangeRequest == null, "can't be clean and still have MeasureRequest");
 
//                 VerifyAccess(); 

                if(!NeverArranged) 
                {
                    ContextLayoutManager ContextLayoutManager = ContextLayoutManager.From(Dispatcher);
                    ContextLayoutManager.ArrangeQueue.Add(this);
                } 

 
                ArrangeDirty = true; 
            }
        } 

        /// 
        /// Invalidates the rendering of the element.
        /// Causes  to be called at a later time. 
        /// 
        public void InvalidateVisual() 
        { 
            InvalidateArrange();
            RenderingInvalidated = true; 
        }


        ///  
        /// Notification that is called by Measure of a child when
        /// it ends up with different desired size for the child. 
        ///  
        /// 
        /// Default implementation simply calls invalidateMeasure(), assuming that layout of a 
        /// parent should be updated after child changed its size.
        /// Finer point: this method can only be called in the scenario when the system calls Measure on a child,
        /// not when parent calls it since if parent calls it, it means parent has dirty layout and is recalculating already.
        ///  
        protected virtual void OnChildDesiredSizeChanged(UIElement child)
        { 
            if(IsMeasureValid) 
            {
                InvalidateMeasure(); 
            }
        }

        ///  
        /// This event fires every time Layout updates the layout of the trees associated with current Dispatcher.
        /// Layout update can happen as a result of some propety change, window resize or explicit user request. 
        ///  
        public event EventHandler LayoutUpdated
        { 
            add
            {
                LayoutEventList.ListItem item = getLayoutUpdatedHandler(value);
 
                if(item == null)
                { 
                    //set a weak ref in LM 
                    item = ContextLayoutManager.From(Dispatcher).LayoutEvents.Add(value);
                    addLayoutUpdatedHandler(value, item); 
                }
            }
            remove
            { 
                LayoutEventList.ListItem item = getLayoutUpdatedHandler(value);
 
                if(item != null) 
                {
                    removeLayoutUpdatedHandler(value); 
                    //remove a weak ref from LM
                    ContextLayoutManager.From(Dispatcher).LayoutEvents.Remove(item);
                }
            } 
        }
 
 
        private void addLayoutUpdatedHandler(EventHandler handler, LayoutEventList.ListItem item)
        { 
            object cachedLayoutUpdatedItems = LayoutUpdatedListItemsField.GetValue(this);

            if(cachedLayoutUpdatedItems == null)
            { 
               LayoutUpdatedListItemsField.SetValue(this, item);
               LayoutUpdatedHandlersField.SetValue(this, handler); 
            } 
            else
            { 
                EventHandler cachedLayoutUpdatedHandler = LayoutUpdatedHandlersField.GetValue(this);
                if(cachedLayoutUpdatedHandler != null)
                {
                    //second unique handler is coming in. 
                    //allocate a datastructure
                    Hashtable list = new Hashtable(2); 
 
                    //add previously cached handler
                    list.Add(cachedLayoutUpdatedHandler, cachedLayoutUpdatedItems); 

                    //add new handler
                    list.Add(handler, item);
 
                    LayoutUpdatedHandlersField.ClearValue(this);
                    LayoutUpdatedListItemsField.SetValue(this,list); 
                } 
                else //already have a list
                { 
                    Hashtable list = (Hashtable)cachedLayoutUpdatedItems;
                    list.Add(handler, item);
                }
            } 
        }
 
        private LayoutEventList.ListItem getLayoutUpdatedHandler(EventHandler d) 
        {
            object cachedLayoutUpdatedItems = LayoutUpdatedListItemsField.GetValue(this); 

            if(cachedLayoutUpdatedItems == null)
            {
               return null; 
            }
            else 
            { 
                EventHandler cachedLayoutUpdatedHandler = LayoutUpdatedHandlersField.GetValue(this);
                if(cachedLayoutUpdatedHandler != null) 
                {
                    if(cachedLayoutUpdatedHandler == d) return (LayoutEventList.ListItem)cachedLayoutUpdatedItems;
                }
                else //already have a list 
                {
                    Hashtable list = (Hashtable)cachedLayoutUpdatedItems; 
                    LayoutEventList.ListItem item = (LayoutEventList.ListItem)(list[d]); 
                    return item;
                } 
                return null;
            }
        }
 
        private void removeLayoutUpdatedHandler(EventHandler d)
        { 
            object cachedLayoutUpdatedItems = LayoutUpdatedListItemsField.GetValue(this); 
            EventHandler cachedLayoutUpdatedHandler = LayoutUpdatedHandlersField.GetValue(this);
 
            if(cachedLayoutUpdatedHandler != null) //single handler
            {
                if(cachedLayoutUpdatedHandler == d)
                { 
                    LayoutUpdatedListItemsField.ClearValue(this);
                    LayoutUpdatedHandlersField.ClearValue(this); 
                } 
            }
            else //there is an ArrayList allocated 
            {
                Hashtable list = (Hashtable)cachedLayoutUpdatedItems;
                list.Remove(d);
            } 
        }
 
        ///  
        /// Recursively propagates IsLayoutSuspended flag down to the whole v's sub tree.
        ///  
        internal static void PropagateSuspendLayout(Visual v)
        {
            if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return;
 
            //the subtree is already suspended - happens when already suspended tree is further disassembled
            //no need to walk down in this case 
            if(v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; 

            //  (bug # 1623922) assert that a UIElement has not being 
            //  removed from the visual tree while updating layout.
            if (    Invariant.Strict
                &&  v.CheckFlagsAnd(VisualFlags.IsUIElement)    )
            { 
                UIElement e = (UIElement)v;
                Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); 
            } 

            v.SetFlags(true, VisualFlags.IsLayoutSuspended); 
            v.TreeLevel = 0;

            int count = v.InternalVisualChildrenCount;
 
            for (int i = 0; i < count; i++)
            { 
                Visual cv = v.InternalGetVisualChild(i); 
                if (cv != null)
                { 
                    PropagateSuspendLayout(cv);
                }
            }
        } 

        ///  
        /// Recursively resets IsLayoutSuspended flag on all visuals of the whole v's sub tree. 
        /// For UIElements also re-inserts the UIElement into Measure and / or Arrange update queues
        /// if necessary. 
        /// 
        internal static void PropagateResumeLayout(Visual parent, Visual v)
        {
            if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return; 

            //the subtree is already active - happens when new elements are added to the active tree 
            //elements are created layout-active so they don't need to be specifically unsuspended 
            //no need to walk down in this case
            //if(!v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; 

            //that can be true only on top of recursion, if suspended v is being connected to suspended parent.
            bool parentIsSuspended = parent == null ? false : parent.CheckFlagsAnd(VisualFlags.IsLayoutSuspended);
            uint parentTreeLevel   = parent == null ? 0     : parent.TreeLevel; 

            if(parentIsSuspended) return; 
 
            v.SetFlags(false, VisualFlags.IsLayoutSuspended);
            v.TreeLevel = parentTreeLevel + 1; 

            if (v.CheckFlagsAnd(VisualFlags.IsUIElement))
            {
                //  re-insert UIElement into the update queues 
                UIElement e = (UIElement)v;
 
                Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); 

                bool requireMeasureUpdate = e.MeasureDirty && !e.NeverMeasured && (e.MeasureRequest == null); 
                bool requireArrangeUpdate = e.ArrangeDirty && !e.NeverArranged && (e.ArrangeRequest == null);
                ContextLayoutManager contextLayoutManager = (requireMeasureUpdate || requireArrangeUpdate)
                    ? ContextLayoutManager.From(e.Dispatcher)
                    : null; 

                if (requireMeasureUpdate) 
                { 
                    contextLayoutManager.MeasureQueue.Add(e);
                } 

                if (requireArrangeUpdate)
                {
                    contextLayoutManager.ArrangeQueue.Add(e); 
                }
            } 
 
            int count = v.InternalVisualChildrenCount;
 
            for (int i = 0; i < count; i++)
            {
                Visual cv = v.InternalGetVisualChild(i);
                if (cv != null) 
                {
                    PropagateResumeLayout(v, cv); 
                } 
            }
        } 

        /// 
        /// Updates DesiredSize of the UIElement. Must be called by parents from theor MeasureCore, to form recursive update.
        /// This is first pass of layout update. 
        /// 
        ///  
        /// Measure is called by parents on their children. Internally, Measure calls MeasureCore override on the same object, 
        /// giving it opportunity to compute its DesiredSize.
        /// This method will return immediately if child is not Dirty, previously measured 
        /// and availableSize is the same as cached. 
        /// This method also resets the IsMeasureinvalid bit on the child.
        /// In case when "unbounded measure to content" is needed, parent can use availableSize
        /// as double.PositiveInfinity. Any returned size is OK in this case. 
        /// 
        /// Available size that parent can give to the child. May be infinity (when parent wants to 
        /// measure to content). This is soft constraint. Child can return bigger size to indicate that it wants bigger space and hope 
        /// that parent can throw in scrolling...
        public void Measure(Size availableSize) 
        {
            bool etwTracingEnabled = false;
            long perfElementID = 0;
 
            if (EventTrace.IsEnabled(EventTrace.Flags.PerToolSupport, EventTrace.Level.verbose))
            { 
                perfElementID = PerfService.GetPerfElementID(this); 

                etwTracingEnabled = true; 
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), EventType.StartEvent, perfElementID);
            }

//             VerifyAccess(); 

            // Disable reentrancy during the measure pass.  This is because much work is done 
            // during measure - such as inflating templates, formatting PTS stuff, creating 
            // fonts, etc.  Generally speaking, we cannot survive reentrancy in these code
            // paths. 
            using(Dispatcher.DisableProcessing())
            {
                //enforce that Measure can not receive NaN size .
                if(DoubleUtil.IsNaN(availableSize.Width) || DoubleUtil.IsNaN(availableSize.Height)) 
                    throw new InvalidOperationException(SR.Get(SRID.UIElement_Layout_NaNMeasure));
 
                bool neverMeasured = NeverMeasured; 

                if(neverMeasured) 
                {
                    switchVisibilityIfNeeded(this.Visibility);
                    //to make sure effects are set correctly - otherwise it's not used
                    //simply because it is never pulled by anybody 
                    pushVisualEffects();
                } 
 
                //if Collapsed, we should not Measure, keep dirty bit but remove request
                if (    this.Visibility == Visibility.Collapsed 
                    ||  ((Visual)this).CheckFlagsAnd(VisualFlags.IsLayoutSuspended)    )
                {
                    //reset measure request.
                    if(MeasureRequest != null) 
                        ContextLayoutManager.From(Dispatcher).MeasureQueue.Remove(this);
 
                    //  remember though that parent tried to measure at this size 
                    //  in case when later this element is called to measure incrementally
                    //  it has up-to-date information stored in _previousAvailableSize 
                    if(!DoubleUtil.AreClose(availableSize,  _previousAvailableSize))
                    {
                        //this will ensure that element will be actually re-measured at the new available size
                        //later when it becomes visible. 
                        InvalidateMeasureInternal();
                        _previousAvailableSize = availableSize; 
                    } 

                    return; 
                }

                //your basic bypass. No reason to calc the same thing.
                if(    IsMeasureValid                       //element is clean 
                    && !neverMeasured                       //previously measured
                    && DoubleUtil.AreClose(availableSize,  _previousAvailableSize)) //and contraint matches 
                { 
                    return;
                } 

                NeverMeasured = false;
                Size prevSize = _desiredSize;
 
                //we always want to be arranged, ensure arrange request
                //doing it before OnMeasure prevents unneeded requests from children in the queue 
                InvalidateArrange(); 
                //_measureInProgress prevents OnChildDesiredSizeChange to cause the elements be put
                //into the queue. 

                MeasureInProgress = true;

                Size desiredSize = new Size(0,0); 

                ContextLayoutManager layoutManager = ContextLayoutManager.From(Dispatcher); 
 
                bool gotException = true;
 
                try
                {
                    layoutManager.EnterMeasure();
 
                    desiredSize = MeasureCore(availableSize);
 
                    gotException = false; 
                }
                finally 
                {
                    // reset measure in progress
                    MeasureInProgress = false;
                    _previousAvailableSize = availableSize; 
                    layoutManager.ExitMeasure();
 
                    if(gotException) 
                        layoutManager.SetLastExceptionElement(this);
                } 

                //enforce that MeasureCore can not return PositiveInfinity size even if given Infinte availabel size.
                //Note: NegativeInfinity can not be returned by definition of Size structure.
                if(double.IsPositiveInfinity(desiredSize.Width) || double.IsPositiveInfinity(desiredSize.Height)) 
                    throw new InvalidOperationException(SR.Get(SRID.UIElement_Layout_PositiveInfinityReturned, this.GetType().FullName));
 
                //enforce that MeasureCore can not return NaN size . 
                if(DoubleUtil.IsNaN(desiredSize.Width) || DoubleUtil.IsNaN(desiredSize.Height))
                    throw new InvalidOperationException(SR.Get(SRID.UIElement_Layout_NaNReturned, this.GetType().FullName)); 

                //reset measure dirtiness

                MeasureDirty = false; 
                //reset measure request.
                if(MeasureRequest != null) 
                    ContextLayoutManager.From(Dispatcher).MeasureQueue.Remove(this); 

                //cache availableSize and desired size 
                _desiredSize = desiredSize;

                //notify parent if our desired size changed (watefall effect)
                if(     !MeasureDuringArrange 
                   &&   !DoubleUtil.AreClose(prevSize, desiredSize))
                { 
                    UIElement p; 
                    IContentHost ich;
                    GetUIParentOrICH(out p, out ich); //only one will be returned 
                    if(p != null && !p.MeasureInProgress) //this is what differs this code from signalDesiredSizeChange()
                        p.OnChildDesiredSizeChanged(this);
                    else if(ich != null)
                        ich.OnChildDesiredSizeChanged(this); 
                }
            } 
 
            if (etwTracingEnabled == true)
            { 
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.MEASUREGUID), EventType.EndEvent, perfElementID);
            }
        }
 
         //only one will be returned, whichever found first
        internal void GetUIParentOrICH(out UIElement uiParent, out IContentHost ich) 
        { 
            ich = null;
            uiParent = null; 

            for(Visual v = VisualTreeHelper.GetParent(this) as Visual; v != null; v = VisualTreeHelper.GetParent(v) as Visual)
            {
                ich = v as IContentHost; 
                if (ich != null) break;
 
                if(v.CheckFlagsAnd(VisualFlags.IsUIElement)) 
                {
                    uiParent = (UIElement)v; 
                    break;
                }
            }
        } 

         //walks visual tree up to find UIElement parent within Element Layout Island, so stops the walk if the island's root is found 
        internal UIElement GetUIParentWithinLayoutIsland() 
        {
            UIElement uiParent = null; 

            for(Visual v = VisualTreeHelper.GetParent(this) as Visual; v != null; v = VisualTreeHelper.GetParent(v) as Visual)
            {
                if (v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) 
                {
                    break; 
                } 

                if(v.CheckFlagsAnd(VisualFlags.IsUIElement)) 
                {
                    uiParent = (UIElement)v;
                    break;
                } 
            }
            return uiParent; 
        } 

 
        /// 
        /// Parents or system call this method to arrange the internals of children on a second pass of layout update.
        /// 
        ///  
        /// This method internally calls ArrangeCore override, giving the derived class opportunity
        /// to arrange its children and/or content using final computed size. 
        /// In their ArrangeCore overrides, derived class is supposed to create its visual structure and 
        /// prepare itself for rendering. Arrange is called by parents
        /// from their implementation of ArrangeCore or by system when needed. 
        /// This method sets Bounds=finalSize before calling ArrangeCore.
        /// 
        /// This is the final size and location that parent or system wants this UIElement to assume.
        public void Arrange(Rect finalRect) 
        {
            bool etwTracingEnabled = false; 
            long perfElementID = 0; 

            if (EventTrace.IsEnabled(EventTrace.Flags.PerToolSupport, EventTrace.Level.verbose)) 
            {
                perfElementID = PerfService.GetPerfElementID(this);

                etwTracingEnabled = true; 
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), EventType.StartEvent, perfElementID);
            } 
 
//             VerifyAccess();
 
            // Disable reentrancy during the arrange pass.  This is because much work is done
            // during arrange - such as formatting PTS stuff, creating
            // fonts, etc.  Generally speaking, we cannot survive reentrancy in these code
            // paths. 
            using(Dispatcher.DisableProcessing())
            { 
                //enforce that Arrange can not come with Infinity size or NaN 
                if(    double.IsPositiveInfinity(finalRect.Width)
                    || double.IsPositiveInfinity(finalRect.Height) 
                    || DoubleUtil.IsNaN(finalRect.Width)
                    || DoubleUtil.IsNaN(finalRect.Height)
                  )
                { 
                    DependencyObject parent = GetUIParent() as UIElement;
                    throw new InvalidOperationException( 
                        SR.Get( 
                            SRID.UIElement_Layout_InfinityArrange,
                                (parent == null ? "" : parent.GetType().FullName), 
                                this.GetType().FullName));
                }

 
                //if Collapsed, we should not Arrange, keep dirty bit but remove request
                if (    this.Visibility == Visibility.Collapsed 
                    ||  ((Visual)this).CheckFlagsAnd(VisualFlags.IsLayoutSuspended)    ) 
                {
                    //reset arrange request. 
                    if(ArrangeRequest != null)
                        ContextLayoutManager.From(Dispatcher).ArrangeQueue.Remove(this);

                    //  remember though that parent tried to arrange at this rect 
                    //  in case when later this element is called to arrange incrementally
                    //  it has up-to-date information stored in _finalRect 
                    _finalRect = finalRect; 

                    return; 
                }

                //in case parent did not call Measure on a child, we call it now.
                //parent can skip calling Measure on a child if it does not care about child's size 
                //passing finalSize practically means "set size" because that's what Measure(sz)/Arrange(same_sz) means
                //Note that in case of IsLayoutSuspended (temporarily out of the tree) the MeasureDirty can be true 
                //while it does not indicate that we should re-measure - we just came of Measure that did nothing 
                //because of suspension
                if(   MeasureDirty 
                   || NeverMeasured)
                {
                    try
                    { 
                        MeasureDuringArrange = true;
                        //If never measured - that means "set size", arrange-only scenario 
                        //Otherwise - the parent previosuly measured the element at constriant 
                        //and the fact that we are arranging the measure-dirty element now means
                        //we are not in the UpdateLayout loop but rather in manual sequence of Measure/Arrange 
                        //(like in HwndSource when new RootVisual is attached) so there are no loops and there could be
                        //measure-dirty elements left after previosu single Measure pass) - so need to use cached constraint
                        if(NeverMeasured)
                            Measure(finalRect.Size); 
                        else
                            Measure(_previousAvailableSize); 
                    } 
                    finally
                    { 
                        MeasureDuringArrange = false;
                    }
                }
 
                //bypass - if clean and rect is the same, no need to re-arrange
                if(    !IsArrangeValid 
                    || NeverArranged 
                    || !DoubleUtil.AreClose(finalRect, _finalRect))
                { 
                    bool firstArrange = NeverArranged;
                    NeverArranged = false;
                    ArrangeInProgress = true;
 
                    ContextLayoutManager layoutManager = ContextLayoutManager.From(Dispatcher);
 
                    Size oldSize = RenderSize; 
                    bool sizeChanged = false;
                    bool gotException = true; 

                    try
                    {
                        layoutManager.EnterArrange(); 

                        //This has to update RenderSize 
                        ArrangeCore(finalRect); 

                        //to make sure Clip is tranferred to Visual 
                        ensureClip(finalRect.Size);

                        //  see if we need to call OnRenderSizeChanged on this element
                        sizeChanged = markForSizeChangedIfNeeded(oldSize, RenderSize); 

                        gotException = false; 
                    } 
                    finally
                    { 
                        ArrangeInProgress = false;
                        layoutManager.ExitArrange();

                        if(gotException) 
                            layoutManager.SetLastExceptionElement(this);
                    } 
 
                    _finalRect = finalRect;
 
                    ArrangeDirty = false;

                    //reset request.
                    if(ArrangeRequest != null) 
                        ContextLayoutManager.From(Dispatcher).ArrangeQueue.Remove(this);
 
                    if((sizeChanged || RenderingInvalidated || firstArrange) && IsRenderable()) 
                    {
                        DrawingContext dc = RenderOpen(); 
                        try
                        {
                            if (etwTracingEnabled == true)
                            { 
                                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ONRENDERGUID), EventType.StartEvent, perfElementID);
                            } 
 
                            OnRender(dc);
 
                            if (etwTracingEnabled == true)
                            {
                                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ONRENDERGUID), EventType.EndEvent, perfElementID);
                            } 
                        }
                        finally 
                        { 
                            dc.Close();
                            RenderingInvalidated = false; 
                        }

                        updatePixelSnappingGuidelines();
                    } 

                    if (firstArrange) 
                    { 
                        EndPropertyInitialization();
                    } 
                }
            }

            if (etwTracingEnabled == true) 
            {
                EventTrace.EventProvider.TraceEvent(EventTrace.GuidFromId(EventTraceGuidId.ARRANGEGUID), EventType.EndEvent, perfElementID); 
            } 
        }
 
        /// 
        /// OnRender is called by the base class when the rendering instructions of the UIElement are required.
        /// Note: the drawing instructions sent to DrawingContext are not rendered immediately on the screen
        /// but rather stored and later passed to the rendering engine at proper time. 
        /// Derived classes override this method to draw the content of the UIElement.
        ///  
        protected virtual void OnRender(DrawingContext drawingContext) 
        {
        } 

        private void updatePixelSnappingGuidelines()
        {
            if((!SnapsToDevicePixels) || (_drawingContent == null)) 
            {
                this.VisualXSnappingGuidelines = this.VisualYSnappingGuidelines = null; 
            } 
            else
            { 
                DoubleCollection xLines = this.VisualXSnappingGuidelines;

                if(xLines == null)
                { 
                    xLines = new DoubleCollection();
                    xLines.Add(0d); 
                    xLines.Add(this.RenderSize.Width); 
                    this.VisualXSnappingGuidelines = xLines;
                } 
                else
                {
                // xLines[0] = 0d;  - this already should be so
                // check to avoid potential dirtiness in renderer 
                    int lastGuideline = xLines.Count - 1;
                    if(!DoubleUtil.AreClose(xLines[lastGuideline], this.RenderSize.Width)) 
                        xLines[lastGuideline] = this.RenderSize.Width; 
                }
 
                DoubleCollection yLines = this.VisualYSnappingGuidelines;
                if(yLines == null)
                {
                    yLines = new DoubleCollection(); 
                    yLines.Add(0d);
                    yLines.Add(this.RenderSize.Height); 
                    this.VisualYSnappingGuidelines = yLines; 
                }
                else 
                {
                // yLines[0] = 0d;  - this already should be so
                // check to avoid potential dirtiness in renderer
                    int lastGuideline = yLines.Count - 1; 
                    if(!DoubleUtil.AreClose(yLines[lastGuideline], this.RenderSize.Height))
                        yLines[lastGuideline] = this.RenderSize.Height; 
                } 
            }
        } 

        private bool markForSizeChangedIfNeeded(Size oldSize, Size newSize)
        {
            //already marked for SizeChanged, simply update the newSize 
            bool widthChanged = !DoubleUtil.AreClose(oldSize.Width, newSize.Width);
            bool heightChanged = !DoubleUtil.AreClose(oldSize.Height, newSize.Height); 
 
            SizeChangedInfo info = sizeChangedInfo;
 
            if(info != null)
            {
                info.Update(widthChanged, heightChanged);
                return true; 
            }
            else if(widthChanged || heightChanged) 
            { 
                info = new SizeChangedInfo(this, oldSize, widthChanged, heightChanged);
                sizeChangedInfo = info; 
                ContextLayoutManager.From(Dispatcher).AddToSizeChangedChain(info);

                //
                // This notifies Visual layer that hittest boundary potentially changed 
                //
 
                PropagateFlags( 
                    this,
                    VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate, 
                    VisualProxyFlags.IsSubtreeDirtyForRender);

                return true;
            } 

            //this result is used to determine if we need to call OnRender after Arrange 
            //OnRender is called for 2 reasons - someone called InvalidateVisual - then OnRender is called 
            //on next Arrange, or the size changed.
            return false; 
        }

        /// 
        /// This is invoked after layout update before rendering if the element's RenderSize 
        /// has changed as a result of layout update.
        ///  
        /// Packaged parameters (, includes 
        /// old and new sizes and which dimension actually changes. 
        protected internal virtual void OnRenderSizeChanged(SizeChangedInfo info) 
        {}

        /// 
        /// Measurement override. Implement your size-to-content logic here. 
        /// 
        ///  
        /// MeasureCore is designed to be the main customizability point for size control of layout. 
        /// Element authors should override this method, call Measure on each child element,
        /// and compute their desired size based upon the measurement of the children. 
        /// The return value should be the desired size.
        /// Note: It is required that a parent element calls Measure on each child or they won't be sized/arranged.
        /// Typical override follows a pattern roughly like this (pseudo-code):
        ///  
        ///     
        /// 
        ///     
        ///  
        /// The key aspects of this snippet are:
        ///      
        /// You must call Measure on each child element 
        /// It is common to cache measurement information between the MeasureCore and ArrangeCore method calls
        /// Calling base.MeasureCore is not required. 
        /// Calls to Measure on children are passing either the same availableSize as the parent, or a subset of the area depending
        /// on the type of layout the parent will perform (for example, it would be valid to remove the area
        /// for some border or padding).
        ///      
        /// 
        /// Available size that parent can give to the child. May be infinity (when parent wants to 
        /// measure to content). This is soft constraint. Child can return bigger size to indicate that it wants bigger space and hope 
        /// that parent can throw in scrolling...
        /// Desired Size of the control, given available size passed as parameter. 
        protected virtual Size MeasureCore(Size availableSize)
        {
            //can not return availableSize here - this is too "greedy" and can cause the Infinity to be
            //returned. So the next "reasonable" choice is (0,0). 
            return new Size(0,0);
        } 
 
        /// 
        /// ArrangeCore allows for the customization of the final sizing and positioning of children. 
        /// 
        /// 
        /// Element authors should override this method, call Arrange on each visible child element,
        /// to size and position each child element by passing a rectangle reserved for the child within parent space. 
        /// Note: It is required that a parent element calls Arrange on each child or they won't be rendered.
        /// Typical override follows a pattern roughly like this (pseudo-code): 
        ///  
        ///     
        /// 
        ///      
        /// 
        ///  
        /// The final area within the parent that element should use to arrange itself and its children. 
        protected virtual void ArrangeCore(Rect finalRect)
        { 
            // Set the element size.
            RenderSize = finalRect.Size;

            //Set transform to reflect the offset of finalRect - parents that have multiple children 
            //pass offset in the finalRect to communicate the location of this child withing the parent.
            Transform renderTransform = RenderTransform; 
            if(renderTransform == Transform.Identity) 
                renderTransform = null;
 
            Vector oldOffset = VisualOffset;
            if (!DoubleUtil.AreClose(oldOffset.X, finalRect.X) ||
                !DoubleUtil.AreClose(oldOffset.Y, finalRect.Y))
            { 
                VisualOffset = new Vector(finalRect.X, finalRect.Y);
            } 
 
            if (renderTransform != null)
            { 
                //render transform + layout offset, create a collection
                TransformGroup t = new TransformGroup();

                Point origin = RenderTransformOrigin; 
                bool hasOrigin = (origin.X != 0d || origin.Y != 0d);
                if (hasOrigin) 
                    t.Children.Add(new TranslateTransform(-(finalRect.Width * origin.X), -(finalRect.Height * origin.Y))); 

                t.Children.Add(renderTransform); 

                if (hasOrigin)
                    t.Children.Add(new TranslateTransform(finalRect.Width * origin.X,
                                                          finalRect.Height * origin.Y)); 

                VisualTransform = t; 
            } 
            else
            { 
                VisualTransform = null;
            }
        }
 
        /// 
        /// This is a public read-only property that returns size of the UIElement. 
        /// This size is typcally used to find out where ink of the element will go. 
        /// 
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] 
        public Size RenderSize
        {
            get
            { 
                if (this.Visibility == Visibility.Collapsed)
                    return new Size(); 
                else 
                    return _size;
            } 
            set
            {
                _size = value;
                InvalidateHitTestBounds(); 
            }
        } 
 
        /// 
        /// This method returns the hit-test bounds of a UIElement to the underlying Visual layer. 
        /// 
        internal override Rect GetHitTestBounds()
        {
            Rect hitBounds = new Rect(_size); 

            if (_drawingContent != null) 
            { 
                MediaContext mediaContext = MediaContext.From(Dispatcher);
                BoundsDrawingContextWalker ctx = mediaContext.AcquireBoundsDrawingContextWalker(); 

                Rect resultRect = _drawingContent.GetContentBounds(ctx);
                mediaContext.ReleaseBoundsDrawingContextWalker(ctx);
 
                hitBounds.Union(resultRect);
            } 
 
            return hitBounds;
        } 

        /// 
        /// The RenderTransform dependency property.
        ///  
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty RenderTransformProperty = 
                    DependencyProperty.Register(
                                "RenderTransform", 
                                typeof(Transform),
                                typeof(UIElement),
                                new PropertyMetadata(
                                            Transform.Identity, 
                                            new PropertyChangedCallback(RenderTransform_Changed)));
 
 
        /// 
        /// The RenderTransform property defines the transform that will be applied to UIElement during rendering of its content. 
        /// This transform does not affect layout of the panel into which the UIElement is nested - the layout does not take this
        /// transform into account to determine the location and RenderSize of the UIElement.
        /// 
        public Transform RenderTransform 
        {
            get { return (Transform) GetValue(RenderTransformProperty); } 
            set { SetValue(RenderTransformProperty, value); } 
        }
 
        private static void RenderTransform_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = (UIElement)d;
 
            //if never measured, then nothing to do, it should be measured at some point
            if(!uie.NeverMeasured && !uie.NeverArranged) 
            { 
                // If the change is simply a subproperty change, there is no
                //  need to Arrange. (which combines RenderTransform with all the 
                //  other transforms.)
                if (!e.IsASubPropertyChange)
                {
                    uie.InvalidateArrange(); 
                    uie.AreTransformsClean = false;
                } 
            } 
        }
 
        /// 
        /// The RenderTransformOrigin dependency property.
        /// 
        ///  
        public static readonly DependencyProperty RenderTransformOriginProperty =
                    DependencyProperty.Register( 
                                "RenderTransformOrigin", 
                                typeof(Point),
                                typeof(UIElement), 
                                new PropertyMetadata(
                                            new Point(0d,0d),
                                            new PropertyChangedCallback(RenderTransformOrigin_Changed)),
                                new ValidateValueCallback(IsRenderTransformOriginValid)); 

 
        private static bool IsRenderTransformOriginValid(object value) 
        {
            Point v = (Point)value; 
            return (    (!DoubleUtil.IsNaN(v.X) && !Double.IsPositiveInfinity(v.X) && !Double.IsNegativeInfinity(v.X))
                     && (!DoubleUtil.IsNaN(v.Y) && !Double.IsPositiveInfinity(v.Y) && !Double.IsNegativeInfinity(v.Y)));
        }
 

        ///  
        /// The RenderTransformOrigin property defines the center of the RenderTransform relative to 
        /// bounds of the element. It is a Point and both X and Y components are between 0 and 1.0 - the
        /// (0,0) is the default value and specified top-left corner of the element, (0.5, 0.5) is the center of element 
        /// and (1,1) is the bottom-right corner of element.
        /// 
        public Point RenderTransformOrigin
        { 
            get { return (Point)GetValue(RenderTransformOriginProperty); }
            set { SetValue(RenderTransformOriginProperty, value); } 
        } 

        private static void RenderTransformOrigin_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            UIElement uie = (UIElement)d;

            //if never measured, then nothing to do, it should be measured at some point 
            if(!uie.NeverMeasured && !uie.NeverArranged)
            { 
                uie.InvalidateArrange(); 
                uie.AreTransformsClean = false;
            } 
        }

        /// 
        /// OnVisualParentChanged is called when the parent of the Visual is changed. 
        /// 
        /// Old parent or null if the Visual did not have a parent before. 
        protected internal override void OnVisualParentChanged(DependencyObject oldParent) 
        {
            // Synchronize ForceInherit properties 
            if (_parent != null)
            {
                DependencyObject parent = _parent;
 
                if (!InputElement.IsUIElement(parent) && !InputElement.IsUIElement3D(parent))
                { 
                    Visual parentAsVisual = parent as Visual; 

                    if (parentAsVisual != null) 
                    {
                        // We are being plugged into a non-UIElement visual. This
                        // means that our parent doesn't play by the same rules we
                        // do, so we need to track changes to our ancestors in 
                        // order to bridge the gap.
                        parentAsVisual.VisualAncestorChanged += new AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); 
 
                        // Try to find a UIElement ancestor to use for coersion.
                        parent = InputElement.GetContainingUIElement(parentAsVisual); 
                    }
                    else
                    {
                        Visual3D parentAsVisual3D = parent as Visual3D; 

                        if (parentAsVisual3D != null) 
                        { 
                            // We are being plugged into a non-UIElement visual. This
                            // means that our parent doesn't play by the same rules we 
                            // do, so we need to track changes to our ancestors in
                            // order to bridge the gap.
                            parentAsVisual3D.VisualAncestorChanged += new AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit);
 
                            // Try to find a UIElement ancestor to use for coersion.
                            parent = InputElement.GetContainingUIElement(parentAsVisual3D); 
                        } 
                    }
                } 

                if (parent != null)
                {
                    SynchronizeForceInheritProperties(this, null, null, parent); 
                }
                else 
                { 
                    // We don't have a UIElement parent or ancestor, so no
                    // coersions are necessary at this time. 
                }
            }
            else
            { 
                DependencyObject parent = oldParent;
 
                if (!InputElement.IsUIElement(parent) && !InputElement.IsUIElement3D(parent)) 
                {
                    // We are being unplugged from a non-UIElement visual. This 
                    // means that our parent didn't play by the same rules we
                    // do, so we started track changes to our ancestors in
                    // order to bridge the gap.  Now we can stop.
                    if (oldParent is Visual) 
                    {
                        ((Visual) oldParent).VisualAncestorChanged -= new AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); 
                    } 
                    else if (oldParent is Visual3D)
                    { 
                        ((Visual3D) oldParent).VisualAncestorChanged -= new AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit);
                    }

                    // Try to find a UIElement ancestor to use for coersion. 
                    parent = InputElement.GetContainingUIElement(oldParent);
                } 
 
                if (parent != null)
                { 
                    SynchronizeForceInheritProperties(this, null, null, parent);
                }
                else
                { 
                    // We don't have a UIElement parent or ancestor, so no
                    // coersions are necessary at this time. 
                } 
            }
 
            // Synchronize ReverseInheritProperty Flags
            //
            // NOTE: do this AFTER synchronizing force-inherited flags, since
            // they often effect focusability and such. 
            this.SynchronizeReverseInheritPropertyFlags(oldParent, true);
        } 
 
        private void OnVisualAncestorChanged_ForceInherit(object sender, AncestorChangedEventArgs e)
        { 
            // NOTE:
            //
            // We are forced to listen to AncestorChanged events because
            // a UIElement may have raw Visuals between it and its nearest 
            // UIElement parent.  We only care about changes that happen
            // to the visual tree BETWEEN this UIElement and its nearest 
            // UIElement parent.  This is because we can rely on our 
            // nearest UIElement parent to notify us when its force-inherit
            // properties change. 

            DependencyObject parent = null;
            if(e.OldParent == null)
            { 
                // We were plugged into something.
 
                // Find our nearest UIElement parent. 
                parent = InputElement.GetContainingUIElement(_parent);
 
                // See if this parent is a child of the ancestor who's parent changed.
                // If so, we don't care about changes that happen above us.
                if(parent != null && VisualTreeHelper.IsAncestorOf(e.Ancestor, parent))
                { 
                    parent = null;
                } 
            } 
            else
            { 
                // we were unplugged from something.

                // Find our nearest UIElement parent.
                parent = InputElement.GetContainingUIElement(_parent); 

                if(parent != null) 
                { 
                    // If we found a UIElement parent in our subtree, the
                    // break in the visual tree must have been above it, 
                    // so we don't need to respond.
                    parent = null;
                }
                else 
                {
                    // There was no UIElement parent in our subtree, so we 
                    // may be detaching from some UIElement parent above 
                    // the break point in the tree.
                    parent = InputElement.GetContainingUIElement(e.OldParent); 
                }
            }

            if(parent != null) 
            {
                SynchronizeForceInheritProperties(this, null, null, parent); 
            } 
        }
 
        internal void OnVisualAncestorChanged(object sender, AncestorChangedEventArgs e)
        {
            UIElement uie = sender as UIElement;
            if(null != uie) 
                PresentationSource.OnVisualAncestorChanged(uie, e);
        } 
 
        /// 
        /// Helper, gives the UIParent under control of which 
        /// the OnMeasure or OnArrange are currently called.
        /// This may be implemented as a tree walk up until
        /// LayoutElement is found.
        ///  
        internal DependencyObject GetUIParent()
        { 
            return UIElementHelper.GetUIParent(this, false); 
        }
 
        internal DependencyObject GetUIParent(bool continuePastVisualTree)
        {
            return UIElementHelper.GetUIParent(this, continuePastVisualTree);
        } 

        internal DependencyObject GetUIParentNo3DTraversal() 
        { 
            DependencyObject parent = null;
 
            // Try to find a UIElement parent in the visual ancestry.
            DependencyObject myParent = InternalVisualParent;
            parent = InputElement.GetContainingUIElement(myParent, true);
 
            return parent;
        } 
 
        /// 
        ///     Called to get the UI parent of this element when there is 
        ///     no visual parent.
        /// 
        /// 
        ///     Returns a non-null value when some framework implementation 
        ///     of this method has a non-visual parent connection,
        ///  
        protected virtual internal DependencyObject GetUIParentCore() 
        {
            return null; 
        }

        /// 
        /// Call this method to ensure that the whoel subtree of elements that includes this UIElement 
        /// is properly updated.
        ///  
        ///  
        /// This ensures that UIElements with IsMeasureInvalid or IsArrangeInvalid will
        /// get call to their MeasureCore and ArrangeCore, and all computed sizes will be validated. 
        /// This method does nothing if layout is clean but it does work if layout is not clean so avoid calling
        /// it after each change in the element tree. It makes sense to either never call it (system will do this
        /// in a deferred manner) or only call it if you absolutely need updated sizes and positions after you do all changes.
        ///  
        public void UpdateLayout()
        { 
//             VerifyAccess(); 
            ContextLayoutManager.From(Dispatcher).UpdateLayout();
        } 

        internal static void BuildRouteHelper(DependencyObject e, EventRoute route, RoutedEventArgs args)
        {
            if (route == null) 
            {
                throw new ArgumentNullException("route"); 
            } 

            if (args == null) 
            {
                throw new ArgumentNullException("args");
            }
 
            if (args.Source == null)
            { 
                throw new ArgumentException(SR.Get(SRID.SourceNotSet)); 
            }
 
            if (args.RoutedEvent != route.RoutedEvent)
            {
                throw new ArgumentException(SR.Get(SRID.Mismatched_RoutedEvent));
            } 

            // Route via visual tree 
            if (args.RoutedEvent.RoutingStrategy == RoutingStrategy.Direct) 
            {
                UIElement uiElement = e as UIElement; 
                ContentElement contentElement = null;
                UIElement3D uiElement3D = null;

                if (uiElement == null) 
                {
                    contentElement = e as ContentElement; 
 
                    if (contentElement == null)
                    { 
                        uiElement3D = e as UIElement3D;
                    }
                }
 
                // Add this element to route
                if (uiElement != null) 
                { 
                    uiElement.AddToEventRoute(route, args);
                } 
                else if (contentElement != null)
                {
                    contentElement.AddToEventRoute(route, args);
                } 
                else if (uiElement3D != null)
                { 
                    uiElement3D.AddToEventRoute(route, args); 
                }
            } 
            else
            {
                int cElements = 0;
 
                while (e != null)
                { 
                    UIElement uiElement = e as UIElement; 
                    ContentElement contentElement = null;
                    UIElement3D uiElement3D = null; 

                    if (uiElement == null)
                    {
                        contentElement = e as ContentElement; 
                    }
                    if (contentElement == null) 
                    { 
                        uiElement3D = e as UIElement3D;
                    } 

                    // Protect against infinite loops by limiting the number of elements
                    // that we will process.
                    if (cElements++ > MAX_ELEMENTS_IN_ROUTE) 
                    {
                        throw new InvalidOperationException(SR.Get(SRID.TreeLoop)); 
                    } 

                    // Allow the element to adjust source 
                    object newSource = null;
                    if (uiElement != null)
                    {
                        newSource = uiElement.AdjustEventSource(args); 
                    }
                    else if (contentElement != null) 
                    { 
                        newSource = contentElement.AdjustEventSource(args);
                    } 
                    else if (uiElement3D != null)
                    {
                        newSource = uiElement3D.AdjustEventSource(args);
                    } 

                    // Add changed source information to the route 
                    if (newSource != null) 
                    {
                        route.AddSource(newSource); 
                    }

                    // Invoke BuildRouteCore
                    bool continuePastVisualTree = false; 
                    if (uiElement != null)
                    { 
                        continuePastVisualTree = uiElement.BuildRouteCore(route, args); 

                        // Add this element to route 
                        uiElement.AddToEventRoute(route, args);

                        // Get element's visual parent
                        e = uiElement.GetUIParent(continuePastVisualTree); 
                    }
                    else if (contentElement != null) 
                    { 
                        continuePastVisualTree = contentElement.BuildRouteCore(route, args);
 
                        // Add this element to route
                        contentElement.AddToEventRoute(route, args);

                        // Get element's visual parent 
                        e = (DependencyObject) contentElement.GetUIParent(continuePastVisualTree);
                    } 
                    else if (uiElement3D != null) 
                    {
                        continuePastVisualTree = uiElement3D.BuildRouteCore(route, args); 

                        // Add this element to route
                        uiElement3D.AddToEventRoute(route, args);
 
                        // Get element's visual parent
                        e = uiElement3D.GetUIParent(continuePastVisualTree); 
                    } 

                    // If the BuildRouteCore implementation changed the 
                    // args.Source to the route parent, respect it in
                    // the actual route.
                    if (e == args.Source)
                    { 
                        route.AddSource(e);
                    } 
                } 
            }
        } 

        /// 
        ///     Adds a handler for the given attached event
        ///  
        [FriendAccessAllowed] // Built into Core, also used by Framework.
        internal static void AddHandler(DependencyObject d, RoutedEvent routedEvent, Delegate handler) 
        { 
            if (d == null)
            { 
                throw new ArgumentNullException("d");
            }

            Debug.Assert(routedEvent != null, "RoutedEvent must not be null"); 

            UIElement uiElement = d as UIElement; 
            if (uiElement != null) 
            {
                uiElement.AddHandler(routedEvent, handler); 
            }
            else
            {
                ContentElement contentElement = d as ContentElement; 
                if (contentElement != null)
                { 
                    contentElement.AddHandler(routedEvent, handler); 
                }
                else 
                {
                    UIElement3D uiElement3D = d as UIElement3D;
                    if (uiElement3D != null)
                    { 
                        uiElement3D.AddHandler(routedEvent, handler);
                    } 
                    else 
                    {
                        throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement, d.GetType())); 
                    }
                }
            }
        } 

        ///  
        ///     Removes a handler for the given attached event 
        /// 
        [FriendAccessAllowed] // Built into Core, also used by Framework. 
        internal static void RemoveHandler(DependencyObject d, RoutedEvent routedEvent, Delegate handler)
        {
            if (d == null)
            { 
                throw new ArgumentNullException("d");
            } 
 
            Debug.Assert(routedEvent != null, "RoutedEvent must not be null");
 
            UIElement uiElement = d as UIElement;
            if (uiElement != null)
            {
                uiElement.RemoveHandler(routedEvent, handler); 
            }
            else 
            { 
                ContentElement contentElement = d as ContentElement;
                if (contentElement != null) 
                {
                    contentElement.RemoveHandler(routedEvent, handler);
                }
                else 
                {
                    UIElement3D uiElement3D = d as UIElement3D; 
                    if (uiElement3D != null) 
                    {
                        uiElement3D.RemoveHandler(routedEvent, handler); 
                    }
                    else
                    {
                        throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement, d.GetType())); 
                    }
                } 
            } 
        }
 
        #region LoadedAndUnloadedEvents

        ///
        ///     Initiate the processing for [Un]Loaded event broadcast starting at this node 
        /// 
        internal virtual void OnPresentationSourceChanged(bool attached) 
        { 
            // Reset the FocusedElementProperty in order to get LostFocus event
            if (!attached && FocusManager.GetFocusedElement(this)!=null) 
                FocusManager.SetFocusedElement(this, null);
        }

        #endregion LoadedAndUnloadedEvents 

        ///  
        ///     Translates a point relative to this element to coordinates that 
        ///     are relative to the specified element.
        ///  
        /// 
        ///     Passing null indicates that coordinates should be relative to
        ///     the root element in the tree that this element belongs to.
        ///  
        public Point TranslatePoint(Point point, UIElement relativeTo)
        { 
            return InputElement.TranslatePoint(point, this, relativeTo); 
        }
 
        /// 
        ///     Returns the input element within this element that is
        ///     at the specified coordinates relative to this element.
        ///  
        public IInputElement InputHitTest(Point point)
        { 
            IInputElement enabledHit; 
            IInputElement rawHit;
            InputHitTest(point, out enabledHit, out rawHit); 

            return enabledHit;
        }
 
        /// 
        ///     Returns the input element within this element that is 
        ///     at the specified coordinates relative to this element. 
        /// 
        ///  
        ///     This is the coordinate, relative to this element, at which
        ///     to look for elements within this one.
        /// 
        ///  
        ///     This element is the deepest enabled input element that is at the
        ///     specified coordinates. 
        ///  
        /// 
        ///     This element is the deepest input element (not necessarily enabled) 
        ///     that is at the specified coordinates.
        /// 
        internal void InputHitTest(Point pt, out IInputElement enabledHit, out IInputElement rawHit)
        { 
            PointHitTestParameters hitTestParameters = new PointHitTestParameters(pt);
 
            // We store the result of the hit testing here.  Note that the 
            // HitTestResultCallback is an instance method on this class
            // so that it can store the element we hit. 
            InputHitTestResult result = new InputHitTestResult();
            VisualTreeHelper.HitTest(this,
                                     new HitTestFilterCallback(InputHitTestFilterCallback),
                                     new HitTestResultCallback(result.InputHitTestResultCallback), 
                                     hitTestParameters);
 
            DependencyObject candidate = result.Result; 
            rawHit = candidate as IInputElement;
            enabledHit = null; 
            while (candidate != null)
            {
                IContentHost contentHost = candidate as IContentHost;
                if (contentHost != null) 
                {
                    // Do not call IContentHost.InputHitTest if the containing UIElement 
                    // is not enabled. 
                    DependencyObject containingElement = InputElement.GetContainingUIElement(candidate);
 
                    if ((bool)containingElement.GetValue(IsEnabledProperty))
                    {
                        pt = InputElement.TranslatePoint(pt, this, candidate);
                        enabledHit = rawHit = contentHost.InputHitTest(pt); 
                        if (enabledHit != null)
                        { 
                            break; 
                        }
                    } 
                }

                UIElement element = candidate as UIElement;
                if (element != null) 
                {
                    if (rawHit == null) 
                    { 
                        // Earlier we hit a non-IInputElement. This is the first one
                        // we've found, so use that as rawHit. 
                        rawHit = element;
                    }
                    if (element.IsEnabled)
                    { 
                        enabledHit = element;
                        break; 
                    } 
                }
 
                UIElement3D element3D = candidate as UIElement3D;
                if (element3D != null)
                {
                    if (rawHit == null) 
                    {
                        // Earlier we hit a non-IInputElement. This is the first one 
                        // we've found, so use that as rawHit. 
                        rawHit = element3D;
                    } 
                    if (element3D.IsEnabled)
                    {
                        enabledHit = element3D;
                        break; 
                    }
                } 
 
                if (candidate == this)
                { 
                    // We are at the element where the hit-test was initiated.
                    // If we haven't found the hit element by now, we missed
                    // everything.
                    break; 
                }
 
 
                candidate = VisualTreeHelper.GetParentInternal(candidate);
            } 
        }

        private HitTestFilterBehavior InputHitTestFilterCallback(DependencyObject currentNode)
        { 
            HitTestFilterBehavior behavior = HitTestFilterBehavior.Continue;
 
            if(UIElementHelper.IsUIElementOrUIElement3D(currentNode)) 
            {
                if(!UIElementHelper.IsVisible(currentNode)) 
                {
                    // The element we are currently processing is not visible,
                    // so we do not allow hit testing to continue down this
                    // subtree. 
                    behavior = HitTestFilterBehavior.ContinueSkipSelfAndChildren;
                } 
                if(!UIElementHelper.IsHitTestVisible(currentNode)) 
                {
                    // The element we are currently processing is not visible for hit testing, 
                    // so we do not allow hit testing to continue down this
                    // subtree.
                    behavior = HitTestFilterBehavior.ContinueSkipSelfAndChildren;
                } 
            }
            else 
            { 
                // This is just a raw Visual, so it cannot receive input.
                // We allow the hit testing to continue through this visual. 
                //
                // When we report the final input, we will return the containing
                // UIElement.
                behavior = HitTestFilterBehavior.Continue; 
            }
 
            return behavior; 
        }
 
        private class InputHitTestResult
        {
            public HitTestResultBehavior InputHitTestResultCallback(HitTestResult result)
            { 
                _result = result;
                return HitTestResultBehavior.Stop; 
            } 

 
            public DependencyObject Result
            {
                get
                { 
                    return _result != null ? _result.VisualHit : null;
                } 
            } 

            private HitTestResult _result; 
        }

        //
        // Left/Right Mouse Button Cracking Routines: 
        //
 
        internal static RoutedEvent CrackMouseButtonEvent(MouseButtonEventArgs e) 
        {
            RoutedEvent newEvent = null; 

            switch(e.ChangedButton)
            {
                case MouseButton.Left: 
                    if(e.RoutedEvent == Mouse.PreviewMouseDownEvent)
                        newEvent = UIElement.PreviewMouseLeftButtonDownEvent; 
                    else if(e.RoutedEvent == Mouse.MouseDownEvent) 
                        newEvent = UIElement.MouseLeftButtonDownEvent;
                    else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent) 
                        newEvent = UIElement.PreviewMouseLeftButtonUpEvent;
                    else
                        newEvent = UIElement.MouseLeftButtonUpEvent;
                    break; 
                case MouseButton.Right:
                    if(e.RoutedEvent == Mouse.PreviewMouseDownEvent) 
                        newEvent = UIElement.PreviewMouseRightButtonDownEvent; 
                    else if(e.RoutedEvent == Mouse.MouseDownEvent)
                        newEvent = UIElement.MouseRightButtonDownEvent; 
                    else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent)
                        newEvent = UIElement.PreviewMouseRightButtonUpEvent;
                    else
                        newEvent = UIElement.MouseRightButtonUpEvent; 
                    break;
                default: 
                    // No wrappers exposed for the other buttons. 
                    break;
            } 
            return ( newEvent );
        }

        private void CrackMouseButtonEventAndReRaiseEvent(MouseButtonEventArgs e) 
        {
            RoutedEvent newEvent = CrackMouseButtonEvent(e); 
 
            if(newEvent != null)
            { 
                ReRaiseEventAs(e, newEvent);
            }
        }
 
        /// 
        ///     A property indicating if the mouse is over this element or not. 
        ///  
        public bool IsMouseDirectlyOver
        { 
            get
            {
                // We do not return the cached value of reverse-inherited seed properties.
                // 
                // The cached value is only used internally to detect a "change".
                // 
                // More Info: 
                // The act of invalidating the seed property of a reverse-inherited property
                // on the first side of the path causes the invalidation of the 
                // reverse-inherited properties on both sides.  The input system has not yet
                // invalidated the seed property on the second side, so its cached value can
                // be incorrect.
                // 
                return IsMouseDirectlyOver_ComputeValue();
            } 
        } 

        private bool IsMouseDirectlyOver_ComputeValue() 
        {
            return (Mouse.DirectlyOver == this);
        }
 
#region new
        ///  
        ///     Asynchronously re-evaluate the reverse-inherited properties. 
        /// 
        [FriendAccessAllowed] 
        internal void SynchronizeReverseInheritPropertyFlags(DependencyObject oldParent, bool isCoreParent)
        {
            if(IsKeyboardFocusWithin)
            { 
                Keyboard.PrimaryDevice.ReevaluateFocusAsync(this, oldParent, isCoreParent);
            } 
 
            // Reevelauate the stylus properties first to guarentee that our property change
            // notifications fire before mouse properties. 
            if(IsStylusOver)
            {
                StylusLogic.CurrentStylusLogicReevaluateStylusOver(this, oldParent, isCoreParent);
            } 

            if(IsStylusCaptureWithin) 
            { 
                StylusLogic.CurrentStylusLogicReevaluateCapture(this, oldParent, isCoreParent);
            } 

            if(IsMouseOver)
            {
                Mouse.PrimaryDevice.ReevaluateMouseOver(this, oldParent, isCoreParent); 
            }
 
            if(IsMouseCaptureWithin) 
            {
                Mouse.PrimaryDevice.ReevaluateCapture(this, oldParent, isCoreParent); 
            }
        }

        ///  
        ///     Controls like popup want to control updating parent properties. This method
        ///     provides an opportunity for those controls to participate and block it. 
        ///  
        internal virtual bool BlockReverseInheritance()
        { 
            return false;
        }

        ///  
        ///     A property indicating if the mouse is over this element or not.
        ///  
        public bool IsMouseOver 
        {
            get 
            {
                return ReadFlag(CoreFlags.IsMouseOverCache);
            }
        } 

        ///  
        ///     A property indicating if the stylus is over this element or not. 
        /// 
        public bool IsStylusOver 
        {
            get
            {
                return ReadFlag(CoreFlags.IsStylusOverCache); 
            }
        } 
 
        /// 
        ///     Indicates if Keyboard Focus is anywhere 
        ///     within in the subtree starting at the
        ///     current instance
        /// 
        public bool IsKeyboardFocusWithin 
        {
            get 
            { 
                return ReadFlag(CoreFlags.IsKeyboardFocusWithinCache);
            } 
        }

#endregion new
 
        /// 
        ///     A property indicating if the mouse is captured to this element or not. 
        ///  
        public bool IsMouseCaptured
        { 
            get { return (bool) GetValue(IsMouseCapturedProperty); }
        }

        ///  
        ///     Captures the mouse to this element.
        ///  
        public bool CaptureMouse() 
        {
            return Mouse.Capture(this); 
        }

        /// 
        ///     Releases the mouse capture. 
        /// 
        public void ReleaseMouseCapture() 
        { 
            if (Mouse.Captured == this)
            { 
                Mouse.Capture(null);
            }
        }
 
        /// 
        ///     Indicates if mouse capture is anywhere within the subtree 
        ///     starting at the current instance 
        /// 
        public bool IsMouseCaptureWithin 
        {
            get
            {
                return ReadFlag(CoreFlags.IsMouseCaptureWithinCache); 
            }
        } 
 
        /// 
        ///     A property indicating if the stylus is over this element or not. 
        /// 
        public bool IsStylusDirectlyOver
        {
            get 
            {
                // We do not return the cached value of reverse-inherited seed properties. 
                // 
                // The cached value is only used internally to detect a "change".
                // 
                // More Info:
                // The act of invalidating the seed property of a reverse-inherited property
                // on the first side of the path causes the invalidation of the
                // reverse-inherited properties on both sides.  The input system has not yet 
                // invalidated the seed property on the second side, so its cached value can
                // be incorrect. 
                // 
                return IsStylusDirectlyOver_ComputeValue();
            } 
        }

        private bool IsStylusDirectlyOver_ComputeValue()
        { 
            return (Stylus.DirectlyOver == this);
        } 
 
        /// 
        ///     A property indicating if the stylus is captured to this element or not. 
        /// 
        public bool IsStylusCaptured
        {
            get { return (bool) GetValue(IsStylusCapturedProperty); } 
        }
 
        ///  
        ///     Captures the stylus to this element.
        ///  
        public bool CaptureStylus()
        {
            return Stylus.Capture(this);
        } 

        ///  
        ///     Releases the stylus capture. 
        /// 
        public void ReleaseStylusCapture() 
        {
            Stylus.Capture(null);
        }
 
        /// 
        ///     Indicates if stylus capture is anywhere within the subtree 
        ///     starting at the current instance 
        /// 
        public bool IsStylusCaptureWithin 
        {
            get
            {
                return ReadFlag(CoreFlags.IsStylusCaptureWithinCache); 
            }
        } 
 
        /// 
        ///     A property indicating if the keyboard is focused on this 
        ///     element or not.
        /// 
        public bool IsKeyboardFocused
        { 
            get
            { 
                // We do not return the cached value of reverse-inherited seed properties. 
                //
                // The cached value is only used internally to detect a "change". 
                //
                // More Info:
                // The act of invalidating the seed property of a reverse-inherited property
                // on the first side of the path causes the invalidation of the 
                // reverse-inherited properties on both sides.  The input system has not yet
                // invalidated the seed property on the second side, so its cached value can 
                // be incorrect. 
                //
                return IsKeyboardFocused_ComputeValue(); 
            }
        }

        private bool IsKeyboardFocused_ComputeValue() 
        {
            return (Keyboard.FocusedElement == this); 
        } 

        ///  
        ///     Set a logical focus on the element. If the current keyboard focus is within the same scope move the keyboard on this element.
        /// 
        public bool Focus()
        { 
            if (Keyboard.Focus(this) == this)
            { 
                // Successfully setting the keyboard focus updated the logical focus as well 
                return true;
            } 

            if (Focusable && IsEnabled)
            {
                // If we cannot set keyboard focus then set the logical focus only 
                // Find element's FocusScope and set its FocusedElement if not already set
                // If FocusedElement is already set we don't want to steal focus for that scope 
                DependencyObject focusScope = FocusManager.GetFocusScope(this); 
                if (FocusManager.GetFocusedElement(focusScope) == null)
                { 
                    FocusManager.SetFocusedElement(focusScope, (IInputElement)this);
                }
            }
 
            // Return false because current KeyboardFocus is not set on the element - only the logical focus is set
            return false; 
        } 

        ///  
        ///     Request to move the focus from this element to another element
        /// 
        /// Determine how to move the focus
        ///  Returns true if focus is moved successfully. Returns false if there is no next element 
        public virtual bool MoveFocus(TraversalRequest request)
        { 
            return false; 
        }
 
        /// 
        ///     Request to predict the element that should receive focus relative to this element for a
        /// given direction, without actually moving focus to it.
        ///  
        /// The direction for which focus should be predicted
        ///  
        ///     Returns the next element that focus should move to for a given FocusNavigationDirection. 
        /// Returns null if focus cannot be moved relative to this element.
        ///  
        public virtual DependencyObject PredictFocus(FocusNavigationDirection direction)
        {
            return null;
        } 

        ///  
        ///     The access key for this element was invoked. Base implementation sets focus to the element. 
        /// 
        /// The arguments to the access key event 
        protected virtual void OnAccessKey(AccessKeyEventArgs e)
        {
            this.Focus();
        } 

 
        ///  
        ///     A property indicating if the inptu method is enabled.
        ///  
        public bool IsInputMethodEnabled
        {
            get { return (bool) GetValue(InputMethod.IsInputMethodEnabledProperty); }
        } 

        ///  
        ///     The Opacity property. 
        /// 
        public static readonly DependencyProperty OpacityProperty = 
                    DependencyProperty.Register(
                                "Opacity",
                                typeof(double),
                                typeof(UIElement), 
                                new UIPropertyMetadata(
                                            1.0d, 
                                            new PropertyChangedCallback(Opacity_Changed))); 

 
        private static void Opacity_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = (UIElement) d;
            uie.pushOpacity(); 
        }
 
        ///  
        /// Opacity applied to the rendered content of the UIElement.  When set, this opacity value
        /// is applied uniformly to the entire UIElement. 
        /// 
        [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
        public double Opacity
        { 
            get { return (double) GetValue(OpacityProperty); }
            set { SetValue(OpacityProperty, value); } 
        } 

        private void pushOpacity() 
        {
            if(this.Visibility == Visibility.Visible)
            {
                base.VisualOpacity = Opacity; 
            }
        } 
 
        /// 
        ///     The OpacityMask property. 
        /// 
        public static readonly DependencyProperty OpacityMaskProperty
            = DependencyProperty.Register("OpacityMask", typeof(Brush), typeof(UIElement),
                                          new UIPropertyMetadata(new PropertyChangedCallback(OpacityMask_Changed))); 

        private static void OpacityMask_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
            UIElement uie = (UIElement) d;
            uie.pushOpacityMask(); 
        }

        /// 
        /// OpacityMask applied to the rendered content of the UIElement.  When set, the alpha channel 
        /// of the Brush's rendered content is applied to the rendered content of the UIElement.
        /// The other channels of the Brush's rendered content (e.g., Red, Green, or Blue) are ignored. 
        ///  
        public Brush OpacityMask
        { 
            get { return (Brush) GetValue(OpacityMaskProperty); }
            set { SetValue(OpacityMaskProperty, value); }
        }
 
        private void pushOpacityMask()
        { 
            base.VisualOpacityMask = OpacityMask; 
        }
 
        /// 
        ///     The BitmapEffect property.
        /// 
        public static readonly DependencyProperty BitmapEffectProperty = 
                DependencyProperty.Register(
                        "BitmapEffect", 
                        typeof(BitmapEffect), 
                        typeof(UIElement),
                        new UIPropertyMetadata(new PropertyChangedCallback(OnBitmapEffectChanged))); 

        private static void OnBitmapEffectChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = (UIElement)d; 
            uie.pushBitmapEffect();
        } 
 
        /// 
        /// BitmapEffect applied to the rendered content of the UIElement. 
        /// 
        public BitmapEffect BitmapEffect
        {
            get { return (BitmapEffect) GetValue(BitmapEffectProperty); } 
            set { SetValue(BitmapEffectProperty, value); }
        } 
 
        private void pushBitmapEffect()
        { 
            base.VisualBitmapEffect = BitmapEffect;
        }

        ///  
        ///     The BitmapEffectInput property.
        ///  
        public static readonly DependencyProperty BitmapEffectInputProperty = 
                DependencyProperty.Register(
                        "BitmapEffectInput", 
                        typeof(BitmapEffectInput),
                        typeof(UIElement),
                        new UIPropertyMetadata(new PropertyChangedCallback(OnBitmapEffectInputChanged)));
 
        private static void OnBitmapEffectInputChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            ((UIElement) d).pushBitmapEffectInput((BitmapEffectInput) e.NewValue); 
        }
 
        /// 
        /// BitmapEffectInput accessor.
        /// 
        public BitmapEffectInput BitmapEffectInput 
        {
            get { return (BitmapEffectInput) GetValue(BitmapEffectInputProperty); } 
            set { SetValue(BitmapEffectInputProperty, value); } 
        }
 

        private void pushBitmapEffectInput(BitmapEffectInput newValue)
        {
            base.VisualBitmapEffectInput = newValue; 
        }
 
        private static void EdgeMode_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            UIElement uie = (UIElement) d; 
            uie.pushEdgeMode();
        }

        private void pushEdgeMode() 
        {
            base.VisualEdgeMode = RenderOptions.GetEdgeMode(this); 
        } 

        private static void BitmapScalingMode_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            UIElement uie = (UIElement) d;
            uie.pushBitmapScalingMode();
        } 

        private void pushBitmapScalingMode() 
        { 
            base.VisualBitmapScalingMode = RenderOptions.GetBitmapScalingMode(this);
        } 


        /// 
        /// pushVisualEffects - helper to propagate Opacity, OpacityMask, BitmapEffect, BitmapScalingMode and EdgeMode 
        /// 
        private void pushVisualEffects() 
        { 
            pushOpacity();
            pushOpacityMask(); 
            pushBitmapEffect();
            pushEdgeMode();
            pushBitmapScalingMode();
        } 

        ///  
        ///     The Visibility property. 
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty VisibilityProperty =
                DependencyProperty.Register(
                        "Visibility",
                        typeof(Visibility), 
                        typeof(UIElement),
                        new PropertyMetadata( 
                                VisibilityBoxes.VisibleBox, 
                                new PropertyChangedCallback(OnVisibilityChanged)),
                        new ValidateValueCallback(ValidateVisibility)); 

        private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = (UIElement) d; 

            Visibility newVisibility = (Visibility) e.NewValue; 
            uie.VisibilityCache = newVisibility; 
            uie.switchVisibilityIfNeeded(newVisibility);
 
            // The IsVisible property depends on this property.
            uie.UpdateIsVisibleCache();
        }
 
        private static bool ValidateVisibility(object o)
        { 
            Visibility value = (Visibility) o; 
            return (value == Visibility.Visible) || (value == Visibility.Hidden) || (value == Visibility.Collapsed);
        } 

        /// 
        ///     Visibility accessor
        ///  
        [Localizability(LocalizationCategory.None, Readability = Readability.Unreadable)]
        public Visibility Visibility 
        { 
            get { return VisibilityCache; }
            set { SetValue(VisibilityProperty, VisibilityBoxes.Box(value)); } 
        }

        private void switchVisibilityIfNeeded(Visibility visibility)
        { 
            switch(visibility)
            { 
                case Visibility.Visible: 
                    ensureVisible();
                    break; 

                case Visibility.Hidden:
                    ensureInvisible(false);
                    break; 

                case Visibility.Collapsed: 
                    ensureInvisible(true); 
                    break;
            } 
        }

        private void ensureVisible()
        { 
            if(ReadFlag(CoreFlags.IsOpacitySuppressed))
            { 
                //restore Opacity 
                base.VisualOpacity = Opacity;
 
                if(ReadFlag(CoreFlags.IsCollapsed))
                {
                    WriteFlag(CoreFlags.IsCollapsed, false);
 
                    //invalidate parent if needed
                    signalDesiredSizeChange(); 
 
                    //we are suppressing rendering (see IsRenderable) of collapsed children (to avoid
                    //confusion when they see RenderSize=(0,0) reported for them) 
                    //so now we should invalidate to re-render if some rendering props
                    //changed while UIElement was Collapsed (Arrange will cause re-rendering)
                    InvalidateVisual();
                } 

                WriteFlag(CoreFlags.IsOpacitySuppressed, false); 
            } 
        }
 
        private void ensureInvisible(bool collapsed)
        {
            if(!ReadFlag(CoreFlags.IsOpacitySuppressed))
            { 
                base.VisualOpacity = 0;
                WriteFlag(CoreFlags.IsOpacitySuppressed, true); 
            } 

            if(!ReadFlag(CoreFlags.IsCollapsed) && collapsed) //Hidden or Visible->Collapsed 
            {
                WriteFlag(CoreFlags.IsCollapsed, true);

                //invalidate parent 
                signalDesiredSizeChange();
            } 
            else if(ReadFlag(CoreFlags.IsCollapsed) && !collapsed) //Collapsed -> Hidden 
            {
                WriteFlag(CoreFlags.IsCollapsed, false); 

                //invalidate parent
                signalDesiredSizeChange();
            } 
        }
 
        private void signalDesiredSizeChange() 
        {
            UIElement p; 
            IContentHost ich;

            GetUIParentOrICH(out p, out ich); //only one will be returned
 
            if(p != null)
                p.OnChildDesiredSizeChanged(this); 
            else if(ich != null) 
                ich.OnChildDesiredSizeChanged(this);
        } 

        private void ensureClip(Size layoutSlotSize)
        {
            Geometry clipGeometry = GetLayoutClip(layoutSlotSize); 

            if(Clip != null) 
            { 
                if(clipGeometry == null)
                    clipGeometry = Clip; 
                else
                {
                    CombinedGeometry cg = new CombinedGeometry(
                        GeometryCombineMode.Intersect, 
                        clipGeometry,
                        Clip); 
 
                    clipGeometry = cg;
                } 
            }

            ChangeVisualClip(clipGeometry, true /* dontSetWhenClose */);
        } 

        ///  
        /// HitTestCore implements precise hit testing against render contents 
        /// 
        protected override HitTestResult HitTestCore(PointHitTestParameters hitTestParameters) 
        {
            if (_drawingContent != null)
            {
                if (_drawingContent.HitTestPoint(hitTestParameters.HitPoint)) 
                {
                    return new PointHitTestResult(this, hitTestParameters.HitPoint); 
                } 
            }
 
            return null;
        }

        ///  
        /// HitTestCore implements precise hit testing against render contents
        ///  
        protected override GeometryHitTestResult HitTestCore(GeometryHitTestParameters hitTestParameters) 
        {
            if ((_drawingContent != null) && GetHitTestBounds().IntersectsWith(hitTestParameters.Bounds)) 
            {
                IntersectionDetail intersectionDetail;

                intersectionDetail = _drawingContent.HitTestGeometry(hitTestParameters.InternalHitGeometry); 
                Debug.Assert(intersectionDetail != IntersectionDetail.NotCalculated);
 
                if (intersectionDetail != IntersectionDetail.Empty) 
                {
                    return new GeometryHitTestResult(this, intersectionDetail); 
                }
            }

            return null; 
        }
 
        ///  
        /// Opens the DrawingVisual for rendering. The returned DrawingContext can be used to
        /// render into the DrawingVisual. 
        /// 
        [FriendAccessAllowed]
        internal DrawingContext RenderOpen()
        { 
            return new VisualDrawingContext(this);
        } 
 
        /// 
        /// Precomputes the render data content. 
        /// 
        internal override void PrecomputeContent()
        {
            base.PrecomputeContent(); 

            if (_drawingContent != null) 
            { 
                _drawingContent.PrecomputeContent();
                bool requiresRealizations = _drawingContent.ContentRequiresRealizationUpdates; 
                // Set the NodeUsesRealizationCaches flag for this content.
                SetFlags(requiresRealizations, VisualFlags.NodeUsesRealizationCaches);

                SetFlags(_drawingContent.ContentIntroducesGraphness, VisualFlags.NodeOrDescendantIntroducesGraphness); 
            }
        } 
 
        /// 
        /// Called from the DrawingContext when the DrawingContext is closed. 
        /// 
        internal override void RenderClose(IDrawingContent newContent)
        {
            VisualFlags flags = VisualFlags.IsSubtreeDirtyForPrecompute | VisualFlags.NodeNeedsBitmapEffectUpdate; 

            IDrawingContent oldContent = _drawingContent; 
 
            //this element does not render - return
            if(oldContent == null && newContent == null) 
                return;

            //
            // First cleanup the old content and the state associate with this node 
            // related to it's content.
            // 
 
            _drawingContent = null;
 
            if (oldContent != null)
            {
                //
                // Remove the notification handlers. 
                //
 
                oldContent.PropagateChangedHandler(ContentsChangedHandler, false /* remove */); 

 
                //
                // Disconnect the old content from this visual.
                //
 
                DisconnectAttachedResource(
                    VisualProxyFlags.IsContentConnected, 
                    ((DUCE.IResource)oldContent)); 
            }
 

            //
            // Prepare the new content.
            // 

            if (newContent != null) 
            { 
                // Propagate notification handlers.
                newContent.PropagateChangedHandler(ContentsChangedHandler, true /* adding */); 

                // Might need a new realization if this content contains text.
                SetFlags(true, VisualFlags.NodeRequiresNewRealization);
                flags |= VisualFlags.NodeInSubtreeRequiresNewRealization; 
            }
 
            _drawingContent = newContent; 

 
            //
            // Mark the visual dirty on all channels and propagate
            // the flags up the parent chain.
            // 

            SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty); 
 
            PropagateFlags(
                this, 
                flags,
                VisualProxyFlags.IsSubtreeDirtyForRender);
        }
 
        /// 
        /// Overriding this function to release DUCE resources during Dispose and during removal of a subtree. 
        ///  
        /// 
        /// Critical - calls other critical code (base) 
        /// 
        [SecurityCritical]
        internal override void FreeContent(DUCE.Channel channel)
        { 
            Debug.Assert(_proxy.IsOnChannel(channel));
 
            if (_drawingContent != null) 
            {
                if (CheckFlagsAnd(channel, VisualProxyFlags.IsContentConnected)) 
                {
                    DUCE.CompositionNode.SetContent(
                        _proxy.GetHandle(channel),
                        DUCE.ResourceHandle.Null, 
                        channel);
 
                    ((DUCE.IResource)_drawingContent).ReleaseOnChannel(channel); 

                    SetFlags(channel, false, VisualProxyFlags.IsContentConnected); 
                }
            }

            // Call the base method too 
            base.FreeContent(channel);
        } 
 
        /// 
        /// Returns the bounding box of the content. 
        /// 
        internal override Rect GetContentBounds()
        {
            if (_drawingContent != null) 
            {
                Rect resultRect = Rect.Empty; 
                MediaContext mediaContext = MediaContext.From(Dispatcher); 
                BoundsDrawingContextWalker ctx = mediaContext.AcquireBoundsDrawingContextWalker();
 
                resultRect = _drawingContent.GetContentBounds(ctx);
                mediaContext.ReleaseBoundsDrawingContextWalker(ctx);

                return resultRect; 
            }
            else 
            { 
                return Rect.Empty;
            } 
        }

        /// 
        /// WalkContent - method which walks the content (if present) and calls out to the 
        /// supplied DrawingContextWalker.
        ///  
        ///  
        ///   DrawingContextWalker - the target of the calls which occur during
        ///   the content walk. 
        /// 
        internal void WalkContent(DrawingContextWalker walker)
        {
            VerifyAPIReadOnly(); 

            if (_drawingContent != null) 
            { 
                _drawingContent.WalkContent(walker);
            } 
        }

        /// 
        /// RenderContent is implemented by derived classes to hook up their 
        /// content. The implementer of this function can assert that the visual
        /// resource is valid on a channel when the function is executed. 
        ///  
        internal override void RenderContent(RenderContext ctx, bool isOnChannel)
        { 
            DUCE.Channel channel = ctx.Channel;

            Debug.Assert(!CheckFlagsAnd(channel, VisualProxyFlags.IsContentConnected));
            Debug.Assert(_proxy.IsOnChannel(channel)); 

 
            // 
            // Create the content on the channel.
            // 

            if (_drawingContent != null)
            {
                DUCE.IResource drawingContent = (DUCE.IResource)_drawingContent; 

                drawingContent.AddRefOnChannel(channel); 
 
                // Hookup it up to the composition node.
 
                DUCE.CompositionNode.SetContent(
                    _proxy.GetHandle(channel),
                    drawingContent.GetHandle(channel),
                    channel); 

                SetFlags( 
                    channel, 
                    true,
                    VisualProxyFlags.IsContentConnected); 
            }
            else if (isOnChannel) /* _drawingContent == null */
            {
                DUCE.CompositionNode.SetContent( 
                    _proxy.GetHandle(channel),
                    DUCE.ResourceHandle.Null, 
                    channel); 
            }
        } 

        /// 
        /// Called by the base class to update realization caches.
        /// Updates the realization cache on the content. 
        /// 
        internal override void UpdateRealizations(RealizationContext ctx) 
        { 
            if (_drawingContent != null)
            { 
                _drawingContent.UpdateRealizations(ctx);
            }
        }
 
        /// 
        /// GetDrawing - Returns the drawing content of this Visual. 
        ///  
        /// 
        /// Changes to this DrawingGroup will not be propagated to the Visual's content. 
        /// This method is called by both the Drawing property, and VisualTreeHelper.GetDrawing()
        /// 
        internal override DrawingGroup GetDrawing()
        { 
            //
 
 
            VerifyAPIReadOnly();
 
            DrawingGroup drawingGroupContent = null;

            // Convert our content to a DrawingGroup, if content exists
            if (_drawingContent != null) 
            {
                drawingGroupContent = DrawingServices.DrawingGroupFromRenderData((RenderData) _drawingContent); 
            } 

            return drawingGroupContent; 
        }


        ///  
        /// This method supplies an additional (to the  property) clip geometry
        /// that is used to intersect Clip in case if  property is set to "true". 
        /// Typcally, this is a size of layout space given to the UIElement. 
        /// 
        /// Geometry to use as additional clip if ClipToBounds=true 
        protected virtual Geometry GetLayoutClip(Size layoutSlotSize)
        {
            if(ClipToBounds)
            { 
                RectangleGeometry rect = new RectangleGeometry(new Rect(RenderSize));
                rect.Freeze(); 
                return rect; 
            }
            else 
                return null;
        }

        ///  
        /// ClipToBounds Property
        ///  
        [CommonDependencyProperty] 
        public static readonly DependencyProperty ClipToBoundsProperty =
                    DependencyProperty.Register( 
                                "ClipToBounds",
                                typeof(bool),
                                typeof(UIElement),
                                new PropertyMetadata( 
                                        BooleanBoxes.FalseBox, // default value
                                        new PropertyChangedCallback(ClipToBounds_Changed))); 
 
        private static void ClipToBounds_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            UIElement uie = (UIElement) d;
            uie.ClipToBoundsCache = (bool) e.NewValue;

            //if never measured, then nothing to do, it should be measured at some point 
            if(!uie.NeverMeasured || !uie.NeverArranged)
            { 
                uie.InvalidateArrange(); 
            }
        } 

        /// 
        /// ClipToBounds Property
        ///  
        /// 
        /// This property enables the content of this UIElement to be clipped by automatic Layout 
        /// in order to "fit" into small space even if the content is larger. 
        /// For example, if a text string is longer then available space, and Layout can not give it the
        /// "full" space to render, setting this property to "true" will ensure that the part of text string that 
        /// does not fit will be automatically clipped.
        /// 
        public bool ClipToBounds
        { 
            get { return ClipToBoundsCache; }
            set { SetValue(ClipToBoundsProperty, BooleanBoxes.Box(value)); } 
        } 

 
        /// 
        /// Clip Property
        /// 
        public static readonly DependencyProperty ClipProperty = 
                    DependencyProperty.Register(
                                "Clip", 
                                typeof(Geometry), 
                                typeof(UIElement),
                                new PropertyMetadata( 
                                            (Geometry) null,
                                            new PropertyChangedCallback(Clip_Changed)));

        private static void Clip_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            UIElement uie = (UIElement) d; 
 
            // if never measured, then nothing to do, it should be measured at some point
            if(!uie.NeverMeasured || !uie.NeverArranged) 
            {
                uie.InvalidateArrange();
            }
        } 

        ///  
        /// Clip Property 
        /// 
        public Geometry Clip 
        {
            get { return (Geometry) GetValue(ClipProperty); }
            set { SetValue(ClipProperty, value); }
        } 

 
        ///  
        /// Align Property
        ///  
        public static readonly DependencyProperty SnapsToDevicePixelsProperty =
                DependencyProperty.Register(
                        "SnapsToDevicePixels",
                        typeof(bool), 
                        typeof(UIElement),
                        new PropertyMetadata( 
                                BooleanBoxes.FalseBox, 
                                new PropertyChangedCallback(SnapsToDevicePixels_Changed)));
 
        private static void SnapsToDevicePixels_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = (UIElement) d;
            uie.SnapsToDevicePixelsCache = (bool) e.NewValue; 

            // if never measured, then nothing to do, it should be measured at some point 
            if(!uie.NeverMeasured || !uie.NeverArranged) 
            {
                uie.InvalidateArrange(); 
            }
        }

        ///  
        /// SnapsToDevicePixels Property
        ///  
        public bool SnapsToDevicePixels 
        {
            get { return SnapsToDevicePixelsCache; } 
            set { SetValue(SnapsToDevicePixelsProperty, value); }
        }

 

 
        // Internal accessor for AccessKeyManager class 
        internal void InvokeAccessKey(AccessKeyEventArgs e)
        { 
            OnAccessKey(e);
        }

        ///  
        ///     GotFocus event
        ///  
        public static readonly RoutedEvent GotFocusEvent = FocusManager.GotFocusEvent.AddOwner(typeof(UIElement)); 

        ///  
        ///     An event announcing that IsFocused changed to true.
        /// 
        public event RoutedEventHandler GotFocus
        { 
            add { AddHandler(GotFocusEvent, value); }
            remove { RemoveHandler(GotFocusEvent, value); } 
        } 

        ///  
        ///     LostFocus event
        /// 
        public static readonly RoutedEvent LostFocusEvent = FocusManager.LostFocusEvent.AddOwner(typeof(UIElement));
 
        /// 
        ///     An event announcing that IsFocused changed to false. 
        ///  
        public event RoutedEventHandler LostFocus
        { 
            add { AddHandler(LostFocusEvent, value); }
            remove { RemoveHandler(LostFocusEvent, value); }
        }
 
        /// 
        ///     The DependencyProperty for the IsFocused property. 
        ///  
        internal static readonly DependencyPropertyKey IsFocusedPropertyKey =
                    DependencyProperty.RegisterReadOnly( 
                                "IsFocused",
                                typeof(bool),
                                typeof(UIElement),
                                new PropertyMetadata( 
                                            BooleanBoxes.FalseBox, // default value
                                            new PropertyChangedCallback(IsFocused_Changed))); 
 
        /// 
        ///     The DependencyProperty for IsFocused. 
        ///     Flags:              None
        ///     Read-Only:          true
        /// 
        public static readonly DependencyProperty IsFocusedProperty 
            = IsFocusedPropertyKey.DependencyProperty;
 
        private static void IsFocused_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        {
            UIElement uiElement = ((UIElement)d); 

            if ((bool) e.NewValue)
            {
                uiElement.OnGotFocus(new RoutedEventArgs(GotFocusEvent, uiElement)); 
            }
            else 
            { 
                uiElement.OnLostFocus(new RoutedEventArgs(LostFocusEvent, uiElement));
            } 
        }

        /// 
        ///     This method is invoked when the IsFocused property changes to true 
        /// 
        /// RoutedEventArgs 
        protected virtual void OnGotFocus(RoutedEventArgs e) 
        {
            RaiseEvent(e); 
        }

        /// 
        ///     This method is invoked when the IsFocused property changes to false 
        /// 
        /// RoutedEventArgs 
        protected virtual void OnLostFocus(RoutedEventArgs e) 
        {
            RaiseEvent(e); 
        }

        /// 
        ///     Gettor for IsFocused Property 
        /// 
        public bool IsFocused 
        { 
            get { return (bool) GetValue(IsFocusedProperty); }
        } 

        //*********************************************************************
        #region IsEnabled Property
        //********************************************************************* 

        ///  
        ///     The DependencyProperty for the IsEnabled property. 
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty IsEnabledProperty =
                    DependencyProperty.Register(
                                "IsEnabled",
                                typeof(bool), 
                                typeof(UIElement),
                                new UIPropertyMetadata( 
                                            BooleanBoxes.TrueBox, // default value 
                                            new PropertyChangedCallback(OnIsEnabledChanged),
                                            new CoerceValueCallback(CoerceIsEnabled))); 


        /// 
        ///     A property indicating if this element is enabled or not. 
        /// 
        public bool IsEnabled 
        { 
            get { return (bool) GetValue(IsEnabledProperty);}
            set { SetValue(IsEnabledProperty, BooleanBoxes.Box(value)); } 
        }

        /// 
        ///     IsEnabledChanged event 
        /// 
        public event DependencyPropertyChangedEventHandler IsEnabledChanged 
        { 
            add {EventHandlersStoreAdd(IsEnabledChangedKey, value);}
            remove {EventHandlersStoreRemove(IsEnabledChangedKey, value);} 
        }
        internal static readonly EventPrivateKey IsEnabledChangedKey = new EventPrivateKey(); // Used by ContentElement

        ///  
        ///     Fetches the value that IsEnabled should be coerced to.
        ///  
        ///  
        ///     This method is virtual is so that controls derived from UIElement
        ///     can combine additional requirements into the coersion logic. 
        ///     

/// It is important for anyone overriding this property to also /// call CoerceValue when any of their dependencies change. /// protected virtual bool IsEnabledCore { get { // As of 1/25/2006, the following controls override this method: // ButtonBase.IsEnabledCore: CanExecute // MenuItem.IsEnabledCore: CanExecute // ScrollBar.IsEnabledCore: _canScroll return true; } } private static object CoerceIsEnabled(DependencyObject d, object value) { UIElement uie = (UIElement) d; // We must be false if our parent is false, but we can be // either true or false if our parent is true. // // Another way of saying this is that we can only be true // if our parent is true, but we can always be false. if((bool) value) { // Our parent can constrain us. We can be plugged into either // a "visual" or "content" tree. If we are plugged into a // "content" tree, the visual tree is just considered a // visual representation, and is normally composed of raw // visuals, not UIElements, so we prefer the content tree. // // The content tree uses the "logical" links. But not all // "logical" links lead to a content tree. // DependencyObject parent = uie.GetUIParentCore() as ContentElement; if(parent == null) { parent = InputElement.GetContainingUIElement(uie._parent); } if(parent == null || (bool)parent.GetValue(IsEnabledProperty)) { return BooleanBoxes.Box(uie.IsEnabledCore); } else { return BooleanBoxes.FalseBox; } } else { return BooleanBoxes.FalseBox; } } private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement uie = (UIElement)d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(IsEnabledChangedKey, e); // Invalidate the children so that they will inherit the new value. InvalidateForceInheritPropertyOnChildren(uie, e.Property); // The input manager needs to re-hittest because something changed // that is involved in the hit-testing we do, so a different result // could be returned. InputManager.SafeCurrentNotifyHitTestInvalidated(); //Notify Automation in case it is interested. AutomationPeer peer = uie.GetAutomationPeer(); if(peer != null) peer.InvalidatePeer(); } //********************************************************************** #endregion IsEnabled Property //********************************************************************* //********************************************************************** #region IsHitTestVisible Property //********************************************************************** ///

/// The DependencyProperty for the IsHitTestVisible property. /// public static readonly DependencyProperty IsHitTestVisibleProperty = DependencyProperty.Register( "IsHitTestVisible", typeof(bool), typeof(UIElement), new UIPropertyMetadata( BooleanBoxes.TrueBox, // default value new PropertyChangedCallback(OnIsHitTestVisibleChanged), new CoerceValueCallback(CoerceIsHitTestVisible))); /// /// A property indicating if this element is hit test visible or not. /// public bool IsHitTestVisible { get { return (bool) GetValue(IsHitTestVisibleProperty); } set { SetValue(IsHitTestVisibleProperty, BooleanBoxes.Box(value)); } } /// /// IsHitTestVisibleChanged event /// public event DependencyPropertyChangedEventHandler IsHitTestVisibleChanged { add {EventHandlersStoreAdd(IsHitTestVisibleChangedKey, value);} remove {EventHandlersStoreRemove(IsHitTestVisibleChangedKey, value);} } internal static readonly EventPrivateKey IsHitTestVisibleChangedKey = new EventPrivateKey(); // Used by ContentElement private static object CoerceIsHitTestVisible(DependencyObject d, object value) { UIElement uie = (UIElement) d; // We must be false if our parent is false, but we can be // either true or false if our parent is true. // // Another way of saying this is that we can only be true // if our parent is true, but we can always be false. if((bool) value) { // Our parent can constrain us. We can be plugged into either // a "visual" or "content" tree. If we are plugged into a // "content" tree, the visual tree is just considered a // visual representation, and is normally composed of raw // visuals, not UIElements, so we prefer the content tree. // // The content tree uses the "logical" links. But not all // "logical" links lead to a content tree. // // However, ContentElements don't understand IsHitTestVisible, // so we ignore them. // DependencyObject parent = InputElement.GetContainingUIElement(uie._parent); if (parent == null || UIElementHelper.IsHitTestVisible(parent)) { return BooleanBoxes.TrueBox; } else { return BooleanBoxes.FalseBox; } } else { return BooleanBoxes.FalseBox; } } private static void OnIsHitTestVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement uie = (UIElement)d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(IsHitTestVisibleChangedKey, e); // Invalidate the children so that they will inherit the new value. InvalidateForceInheritPropertyOnChildren(uie, e.Property); // The input manager needs to re-hittest because something changed // that is involved in the hit-testing we do, so a different result // could be returned. InputManager.SafeCurrentNotifyHitTestInvalidated(); } //********************************************************************* #endregion IsHitTestVisible Property //********************************************************************** //********************************************************************* #region IsVisible Property //********************************************************************* // The IsVisible property is a read-only reflection of the Visibility // property. private static PropertyMetadata _isVisibleMetadata = new ReadOnlyPropertyMetadata(BooleanBoxes.FalseBox, new GetReadOnlyValueCallback(GetIsVisible), new PropertyChangedCallback(OnIsVisibleChanged)); internal static readonly DependencyPropertyKey IsVisiblePropertyKey = DependencyProperty.RegisterReadOnly( "IsVisible", typeof(bool), typeof(UIElement), _isVisibleMetadata); /// /// The DependencyProperty for the IsVisible property. /// public static readonly DependencyProperty IsVisibleProperty = IsVisiblePropertyKey.DependencyProperty; /// /// A property indicating if this element is Visible or not. /// public bool IsVisible { get { return ReadFlag(CoreFlags.IsVisibleCache); } } private static object GetIsVisible(DependencyObject d, out BaseValueSourceInternal source) { source = BaseValueSourceInternal.Local; return ((UIElement)d).IsVisible ? BooleanBoxes.TrueBox : BooleanBoxes.FalseBox; } /// /// IsVisibleChanged event /// public event DependencyPropertyChangedEventHandler IsVisibleChanged { add {EventHandlersStoreAdd(IsVisibleChangedKey, value);} remove {EventHandlersStoreRemove(IsVisibleChangedKey, value);} } internal static readonly EventPrivateKey IsVisibleChangedKey = new EventPrivateKey(); // Used by ContentElement /// /// Critical - Calls a critical method (PresentationSource.CriticalFromVisual) /// TreatAsSafe - No exposure /// [SecurityCritical, SecurityTreatAsSafe] internal void UpdateIsVisibleCache() // Called from PresentationSource { // IsVisible is a read-only property. It derives its "base" value // from the Visibility property. bool isVisible = (Visibility == Visibility.Visible); // We must be false if our parent is false, but we can be // either true or false if our parent is true. // // Another way of saying this is that we can only be true // if our parent is true, but we can always be false. if(isVisible) { bool constraintAllowsVisible = false; // Our parent can constrain us. We can be plugged into either // a "visual" or "content" tree. If we are plugged into a // "content" tree, the visual tree is just considered a // visual representation, and is normally composed of raw // visuals, not UIElements, so we prefer the content tree. // // The content tree uses the "logical" links. But not all // "logical" links lead to a content tree. // // However, ContentElements don't understand IsVisible, // so we ignore them. // DependencyObject parent = InputElement.GetContainingUIElement(_parent); if(parent != null) { constraintAllowsVisible = UIElementHelper.IsVisible(parent); } else { // We cannot be visible if we have no visual parent, unless: // 1) We are the root, connected to a PresentationHost. PresentationSource presentationSource = PresentationSource.CriticalFromVisual(this); if(presentationSource != null) { constraintAllowsVisible = true; } else { // CODE } } if(!constraintAllowsVisible) { isVisible = false; } } if(isVisible != IsVisible) { // Our IsVisible force-inherited property has changed. Update our // cache and raise a change notification. WriteFlag(CoreFlags.IsVisibleCache, isVisible); NotifyPropertyChange(new DependencyPropertyChangedEventArgs(IsVisibleProperty, _isVisibleMetadata, BooleanBoxes.Box(!isVisible), BooleanBoxes.Box(isVisible))); } } private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement uie = (UIElement) d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(IsVisibleChangedKey, e); // Invalidate the children so that they will inherit the new value. InvalidateForceInheritPropertyOnChildren(uie, e.Property); // The input manager needs to re-hittest because something changed // that is involved in the hit-testing we do, so a different result // could be returned. InputManager.SafeCurrentNotifyHitTestInvalidated(); } //********************************************************************* #endregion IsVisible Property //********************************************************************** //********************************************************************* #region Focusable Property //********************************************************************** /// /// The DependencyProperty for the Focusable property. /// [CommonDependencyProperty] public static readonly DependencyProperty FocusableProperty = DependencyProperty.Register( "Focusable", typeof(bool), typeof(UIElement), new UIPropertyMetadata( BooleanBoxes.FalseBox, // default value new PropertyChangedCallback(OnFocusableChanged))); /// /// Gettor and Settor for Focusable Property /// public bool Focusable { get { return (bool) GetValue(FocusableProperty); } set { SetValue(FocusableProperty, BooleanBoxes.Box(value)); } } /// /// FocusableChanged event /// public event DependencyPropertyChangedEventHandler FocusableChanged { add {EventHandlersStoreAdd(FocusableChangedKey, value);} remove {EventHandlersStoreRemove(FocusableChangedKey, value);} } internal static readonly EventPrivateKey FocusableChangedKey = new EventPrivateKey(); // Used by ContentElement private static void OnFocusableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement uie = (UIElement) d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(FocusableChangedKey, e); } //********************************************************************** #endregion Focusable Property //********************************************************************* /// /// Called by the Automation infrastructure when AutomationPeer /// is requested for this element. The element can return null or /// the instance of AutomationPeer-derived clas, if it supports UI Automation /// protected virtual AutomationPeer OnCreateAutomationPeer() { return null; } /// /// Called by the Automation infrastructure or Control author /// to make sure the AutomationPeer is created. The element may /// create AP or return null, depending on OnCreateAutomationPeer override. /// internal AutomationPeer CreateAutomationPeer() { VerifyAccess(); //this will ensure the AP is created in the right context AutomationPeer ap = null; if(HasAutomationPeer) { ap = AutomationPeerField.GetValue(this); } else { ap = OnCreateAutomationPeer(); if(ap != null) { AutomationPeerField.SetValue(this, ap); HasAutomationPeer = true; } } return ap; } /// /// Returns AutomationPeer if one exists. /// The AutomationPeer may not exist if not yet created by Automation infrastructure /// or if this element is not supposed to have one. /// internal AutomationPeer GetAutomationPeer() { VerifyAccess(); if(HasAutomationPeer) return AutomationPeerField.GetValue(this); return null; } /// /// Called by the Automation infrastructure only in the case when the UIElement does not have a specific /// peer (does not override OnCreateAutomationPeer) but we still want some generic peer to be created and cached. /// For example, this is needed when HwndTarget contains a Panel and 2 Buttons underneath - the Panel /// normally does not have a peer so only one of the Buttons is visible in the tree. /// internal AutomationPeer CreateGenericRootAutomationPeer() { VerifyAccess(); //this will ensure the AP is created in the right context AutomationPeer ap = null; // If some peer was already created, specific or generic - use it. if(HasAutomationPeer) { ap = AutomationPeerField.GetValue(this); } else { ap = new GenericRootAutomationPeer(this); AutomationPeerField.SetValue(this, ap); HasAutomationPeer = true; } return ap; } /// /// This is used by the parser and journaling to uniquely identify a given element /// in a deterministic fashion, i.e., each time the same XAML/BAML is parsed/read, /// the items will be given the same PersistId. /// /// To keep PersistId from being serialized the set has been removed from the property and a separate /// set method has been created. [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] [Obsolete("PersistId is an obsolete property and may be removed in a future release. The value of this property is not defined.")] public int PersistId { get { return _persistId; } } /// /// This is used by the parser and journaling to uniquely identify a given element /// in a deterministic fashion, i.e., each time the same XAML/BAML is parsed/read, /// the items will be given the same PersistId. /// /// /// To keep PersistId from being serialized the set has been removed from the property and a separate /// set method has been created. [FriendAccessAllowed] // Built into Core, also used by Framework. internal void SetPersistId(int value) { _persistId = value; } // Helper method to retrieve and fire Clr Event handlers for DependencyPropertyChanged event private void RaiseDependencyPropertyChanged(EventPrivateKey key, DependencyPropertyChangedEventArgs args) { EventHandlersStore store = EventHandlersStore; if (store != null) { Delegate handler = store.Get(key); if (handler != null) { ((DependencyPropertyChangedEventHandler)handler)(this, args); } } } internal Rect PreviousArrangeRect { // called from PresentationFramework!System.Windows.Controls.Primitives.LayoutInformation.GetLayoutSlot() [FriendAccessAllowed] get { return _finalRect; } } // Cache for the Visibility property. Storage is in Visual._nodeProperties. private Visibility VisibilityCache { get { if (CheckFlagsAnd(VisualFlags.VisibilityCache_Visible)) { return Visibility.Visible; } else if (CheckFlagsAnd(VisualFlags.VisibilityCache_TakesSpace)) { return Visibility.Hidden; } else { return Visibility.Collapsed; } } set { Debug.Assert(value == Visibility.Visible || value == Visibility.Hidden || value == Visibility.Collapsed); switch (value) { case Visibility.Visible: SetFlags(true, VisualFlags.VisibilityCache_Visible); SetFlags(false, VisualFlags.VisibilityCache_TakesSpace); break; case Visibility.Hidden: SetFlags(false, VisualFlags.VisibilityCache_Visible); SetFlags(true, VisualFlags.VisibilityCache_TakesSpace); break; case Visibility.Collapsed: SetFlags(false, VisualFlags.VisibilityCache_Visible); SetFlags(false, VisualFlags.VisibilityCache_TakesSpace); break; } } } #region ForceInherit property support // Also called by FrameworkContentElement internal static void SynchronizeForceInheritProperties( UIElement uiElement, ContentElement contentElement, UIElement3D uiElement3D, DependencyObject parent) { if(uiElement != null || uiElement3D != null) { bool parentValue = (bool) parent.GetValue(IsEnabledProperty); if(!parentValue) { // For Read/Write force-inherited properties, use the standard coersion pattern. // // The IsEnabled property must be coerced false if the parent is false. if (uiElement != null) { uiElement.CoerceValue(IsEnabledProperty); } else { uiElement3D.CoerceValue(IsEnabledProperty); } } parentValue = (bool) parent.GetValue(IsHitTestVisibleProperty); if(!parentValue) { // For Read/Write force-inherited properties, use the standard coersion pattern. // // The IsHitTestVisible property must be coerced false if the parent is false. if (uiElement != null) { uiElement.CoerceValue(IsHitTestVisibleProperty); } else { uiElement3D.CoerceValue(IsHitTestVisibleProperty); } } parentValue = (bool) parent.GetValue(IsVisibleProperty); if(parentValue) { // For Read-Only force-inherited properties, use a private update method. // // The IsVisible property can only be true if the parent is true. if (uiElement != null) { uiElement.UpdateIsVisibleCache(); } else { uiElement3D.UpdateIsVisibleCache(); } } } else if(contentElement != null) { bool parentValue = (bool) parent.GetValue(IsEnabledProperty); if(!parentValue) { // The IsEnabled property must be coerced false if the parent is false. contentElement.CoerceValue(IsEnabledProperty); } } } // This is called from the force-inherit property changed events. internal static void InvalidateForceInheritPropertyOnChildren(Visual v, DependencyProperty property) { int cChildren = v.InternalVisual2DOr3DChildrenCount; for (int iChild = 0; iChild < cChildren; iChild++) { DependencyObject child = v.InternalGet2DOr3DVisualChild(iChild); Visual vChild = child as Visual; if (vChild != null) { UIElement element = vChild as UIElement; if (element != null) { if(property == IsVisibleProperty) { // For Read-Only force-inherited properties, use // a private update method. element.UpdateIsVisibleCache(); } else { // For Read/Write force-inherited properties, use // the standard coersion pattern. element.CoerceValue(property); } } else { // We have to "walk through" non-UIElement visuals. InvalidateForceInheritPropertyOnChildren(vChild, property); } } else { Visual3D v3DChild = child as Visual3D; if (v3DChild != null) { UIElement3D element3D = v3DChild as UIElement3D; if(element3D != null) { if(property == IsVisibleProperty) { // For Read-Only force-inherited properties, use // a private update method. element3D.UpdateIsVisibleCache(); } else { // For Read/Write force-inherited properties, use // the standard coersion pattern. element3D.CoerceValue(property); } } else { // We have to "walk through" non-UIElement visuals. UIElement3D.InvalidateForceInheritPropertyOnChildren(v3DChild, property); } } } } } #endregion ///// LAYOUT DATA ///// private Rect _finalRect; private Size _desiredSize; private Size _previousAvailableSize; private IDrawingContent _drawingContent; //right after creation all elements are Clean so go Invalidate at least one internal ContextLayoutManager.LayoutQueue.Request MeasureRequest; internal ContextLayoutManager.LayoutQueue.Request ArrangeRequest; // See PersistId property private int _persistId = 0; ///// ATTACHED STORAGE ///// // Perf analysis showed we were not using these fields enough to warrant // bloating each instance with the field, so storage is created on-demand // in the local store. internal static readonly UncommonField EventHandlersStoreField = new UncommonField(); internal static readonly UncommonField InputBindingCollectionField = new UncommonField(); internal static readonly UncommonField CommandBindingCollectionField = new UncommonField(); private static readonly UncommonField LayoutUpdatedListItemsField = new UncommonField(); private static readonly UncommonField LayoutUpdatedHandlersField = new UncommonField(); private static readonly UncommonField StylusPlugInsField = new UncommonField(); private static readonly UncommonField AutomationPeerField = new UncommonField(); internal SizeChangedInfo sizeChangedInfo; private bool HasAutomationPeer { get { return ReadFlag(CoreFlags.HasAutomationPeer); } set { WriteFlag(CoreFlags.HasAutomationPeer, value); } } private bool RenderingInvalidated { get { return ReadFlag(CoreFlags.RenderingInvalidated); } set { WriteFlag(CoreFlags.RenderingInvalidated, value); } } internal bool SnapsToDevicePixelsCache { get { return ReadFlag(CoreFlags.SnapsToDevicePixelsCache); } set { WriteFlag(CoreFlags.SnapsToDevicePixelsCache, value); } } internal bool ClipToBoundsCache { get { return ReadFlag(CoreFlags.ClipToBoundsCache); } set { WriteFlag(CoreFlags.ClipToBoundsCache, value); } } internal bool MeasureDirty { get { return ReadFlag(CoreFlags.MeasureDirty); } set { WriteFlag(CoreFlags.MeasureDirty, value); } } internal bool ArrangeDirty { get { return ReadFlag(CoreFlags.ArrangeDirty); } set { WriteFlag(CoreFlags.ArrangeDirty, value); } } internal bool MeasureInProgress { get { return ReadFlag(CoreFlags.MeasureInProgress); } set { WriteFlag(CoreFlags.MeasureInProgress, value); } } internal bool ArrangeInProgress { get { return ReadFlag(CoreFlags.ArrangeInProgress); } set { WriteFlag(CoreFlags.ArrangeInProgress, value); } } internal bool NeverMeasured { get { return ReadFlag(CoreFlags.NeverMeasured); } set { WriteFlag(CoreFlags.NeverMeasured, value); } } internal bool NeverArranged { get { return ReadFlag(CoreFlags.NeverArranged); } set { WriteFlag(CoreFlags.NeverArranged, value); } } internal bool MeasureDuringArrange { get { return ReadFlag(CoreFlags.MeasureDuringArrange); } set { WriteFlag(CoreFlags.MeasureDuringArrange, value); } } internal bool AreTransformsClean { get { return ReadFlag(CoreFlags.AreTransformsClean); } set { WriteFlag(CoreFlags.AreTransformsClean, value); } } internal static readonly FocusWithinProperty FocusWithinProperty = new FocusWithinProperty(); internal static readonly MouseOverProperty MouseOverProperty = new MouseOverProperty(); internal static readonly MouseCaptureWithinProperty MouseCaptureWithinProperty = new MouseCaptureWithinProperty(); internal static readonly StylusOverProperty StylusOverProperty = new StylusOverProperty(); internal static readonly StylusCaptureWithinProperty StylusCaptureWithinProperty = new StylusCaptureWithinProperty(); private Size _size; internal const int MAX_ELEMENTS_IN_ROUTE = 256; } [Flags] internal enum CoreFlags : uint { SnapsToDevicePixelsCache = 0x00000001, ClipToBoundsCache = 0x00000002, MeasureDirty = 0x00000004, ArrangeDirty = 0x00000008, MeasureInProgress = 0x00000010, ArrangeInProgress = 0x00000020, NeverMeasured = 0x00000040, NeverArranged = 0x00000080, MeasureDuringArrange = 0x00000100, IsCollapsed = 0x00000200, IsKeyboardFocusWithinCache = 0x00000400, IsKeyboardFocusWithinChanged = 0x00000800, IsMouseOverCache = 0x00001000, IsMouseOverChanged = 0x00002000, IsMouseCaptureWithinCache = 0x00004000, IsMouseCaptureWithinChanged = 0x00008000, IsStylusOverCache = 0x00010000, IsStylusOverChanged = 0x00020000, IsStylusCaptureWithinCache = 0x00040000, IsStylusCaptureWithinChanged = 0x00080000, HasAutomationPeer = 0x00100000, RenderingInvalidated = 0x00200000, IsVisibleCache = 0x00400000, AreTransformsClean = 0x00800000, IsOpacitySuppressed = 0x01000000, ExistsEventHandlersStore = 0x02000000, //FreeBit = 0x04000000, //FreeBit = 0x08000000, //FreeBit = 0x10000000, //FreeBit = 0x20000000, //FreeBit = 0x40000000, //FreeBit = 0x80000000, } } // 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