UIElement3D.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / UIElement3D.cs / 1 / UIElement3D.cs

                            //------------------------------------------------------------------------------ 
//
// 
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//  
//
//----------------------------------------------------------------------------- 
 
using MS.Internal;
using MS.Internal.KnownBoxes; 
using MS.Internal.Media;
using MS.Internal.PresentationCore;
using MS.Utility;
using System; 
using System.Collections;
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Diagnostics;
using System.Security; 
using System.Security.Permissions;
using System.Windows.Automation.Peers;
using System.Windows.Input;
using System.Windows.Input.StylusPlugIns; 
using System.Windows.Interop;
using System.Windows.Markup; 
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects;
using System.Windows.Media.Media3D;
using System.Windows.Threading;
 
namespace System.Windows
{ 
    ///  
    /// UIElement3D is the base class for frameworks building on the Windows Presentation Core.
    ///  
    /// 
    /// UIElement3D adds to the base visual class "IFE" - Input, Focus, and Eventing.
    /// 
    public abstract partial class UIElement3D : Visual3D, IInputElement 
    {
        ///  
        ///  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 UIElement3D()
        {
            UIElement.RegisterEvents(typeof(UIElement3D)); 

            // add owner and then override metadata for IsVisibile 
            IsVisibleProperty = UIElement.IsVisibleProperty.AddOwner(typeof(UIElement3D)); 

            _isVisibleMetadata = new ReadOnlyPropertyMetadata(BooleanBoxes.FalseBox, 
                                                              new GetReadOnlyValueCallback(GetIsVisible),
                                                              new PropertyChangedCallback(OnIsVisibleChanged));

            IsVisibleProperty.OverrideMetadata(typeof(UIElement3D), 
                                               _isVisibleMetadata,
                                               UIElement.IsVisiblePropertyKey); 
 
            // add owner and then override metadta for IsFocused
            IsFocusedProperty = UIElement.IsFocusedProperty.AddOwner(typeof(UIElement3D)); 
            IsFocusedProperty.OverrideMetadata(typeof(UIElement3D),
                                                new PropertyMetadata(
                                                    BooleanBoxes.FalseBox, // default value
                                                    new PropertyChangedCallback(IsFocused_Changed)), 
                                               UIElement.IsFocusedPropertyKey);
        } 
 
        /// 
        /// Constructor. This form of constructor will encounter a slight perf hit since it needs to initialize Dispatcher for the instance. 
        /// 
        protected UIElement3D()
        {
            _children = new Visual3DCollection(this); 

            Initialize(); 
        } 

        private void Initialize() 
        {
            BeginPropertyInitialization();

            VisibilityCache = (Visibility) VisibilityProperty.GetDefaultValue(DependencyObjectType); 

            // Note: IsVisibleCache is false by default. 
 
            // to cause the first render to occur
            InvalidateModel(); 
        }

        #region AllowDrop
 
        /// 
        ///     The DependencyProperty for the AllowDrop property. 
        ///  
        public static readonly DependencyProperty AllowDropProperty =
                    UIElement.AllowDropProperty.AddOwner( 
                                typeof(UIElement3D),
                                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 

        private object CallRenderCallback(object o) 
        { 
            OnUpdateModel();
 
            _renderRequestPosted = false;

            return null;
        } 

        ///  
        /// Invalidates the rendering of the element. 
        /// Causes  to be called at a later time.
        ///  
        public void InvalidateModel()
        {
            if(!_renderRequestPosted)
            { 
                MediaContext.From(Dispatcher).BeginInvokeOnRender(CallRenderCallback, this);
                _renderRequestPosted = true; 
            } 
        }
 
        /// 
        ///      This class provides a point for subclasses to access the protected content of the
        ///      UIElement to set what the geometry they should render should be.
        ///  
        protected virtual void OnUpdateModel()
        { 
        } 

        ///  
        /// OnVisualParentChanged is called when the parent of the Visual3D is changed.
        /// 
        /// Old parent or null if the Visual3D did not have a parent before.
        protected internal override void OnVisualParentChanged(DependencyObject oldParent) 
        {
            // Synchronize ForceInherit properties 
            if (InternalVisualParent != null) 
            {
                DependencyObject parent = InternalVisualParent; 

                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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit);
                    } 
                    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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); 
                        } 
                    }
 
                    // find a UIElement(3D) ancestor to use for coersion
                    parent = InputElement.GetContainingUIElement(parentAsVisual);
                }
 
                if (parent != null)
                { 
                    UIElement.SynchronizeForceInheritProperties(null, null, this, 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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); 
                    }
                    else if (oldParent is Visual3D)
                    {
                        ((Visual3D) oldParent).VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); 
                    }
 
                    // Try to find a UIElement ancestor to use for coersion. 
                    parent = InputElement.GetContainingUIElement(oldParent);
                } 

                if (parent != null)
                {
                    UIElement.SynchronizeForceInheritProperties(null, null, this, 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(InternalVisualParent);

                // 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(InternalVisualParent); 

                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) 
            {
                UIElement.SynchronizeForceInheritProperties(null, null, this, parent); 
            }
        }

        internal void OnVisualAncestorChanged(object sender, AncestorChangedEventArgs e) 
        {
            UIElement3D uie3D = sender as UIElement3D; 
            if(null != uie3D) 
                PresentationSource.OnVisualAncestorChanged(uie3D, e);
        } 

        internal DependencyObject GetUIParent(bool continuePastVisualTree)
        {
            return UIElementHelper.GetUIParent(this, continuePastVisualTree); 
        }
 
        ///  
        ///     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 internal DependencyObject GetUIParentCore() 
        { 
            //
 
            return null;
        }

 
        #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
 
        /// 
        ///     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 Visibility property.
        /// 
        [CommonDependencyProperty] 
        public static readonly DependencyProperty VisibilityProperty =
                            UIElement.VisibilityProperty.AddOwner( 
                                typeof(UIElement3D), 
                                new PropertyMetadata(
                                    VisibilityBoxes.VisibleBox, 
                                    new PropertyChangedCallback(OnVisibilityChanged)));

        private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        { 
            UIElement3D uie = (UIElement3D) 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() 
        {
            InternalIsVisible = true; 
        } 

        private void ensureInvisible(bool collapsed) 
        {
            InternalIsVisible = false;

            if(!ReadFlag(CoreFlags.IsCollapsed) && collapsed) //Hidden or Visible->Collapsed 
            {
                WriteFlag(CoreFlags.IsCollapsed, true); 
            } 
            else if(ReadFlag(CoreFlags.IsCollapsed) && !collapsed) //Collapsed -> Hidden
            { 
                WriteFlag(CoreFlags.IsCollapsed, false);
            }
        }
 
        // Internal accessor for AccessKeyManager class
        internal void InvokeAccessKey(AccessKeyEventArgs e) 
        { 
            OnAccessKey(e);
        } 

        /// 
        ///     GotFocus event
        ///  
        public static readonly RoutedEvent GotFocusEvent = FocusManager.GotFocusEvent.AddOwner(typeof(UIElement3D));
 
        ///  
        ///     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(UIElement3D));

        /// 
        ///     An event announcing that IsFocused changed to false. 
        /// 
        public event RoutedEventHandler LostFocus 
        { 
            add { AddHandler(LostFocusEvent, value); }
            remove { RemoveHandler(LostFocusEvent, value); } 
        }

        /// 
        ///     The DependencyProperty for IsFocused. 
        ///     Flags:              None
        ///     Read-Only:          true 
        ///  
        public static readonly DependencyProperty IsFocusedProperty;
 
        private static void IsFocused_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement3D uiElement3D = ((UIElement3D)d);
 
            if ((bool) e.NewValue)
            { 
                uiElement3D.OnGotFocus(new RoutedEventArgs(GotFocusEvent, uiElement3D)); 
            }
            else 
            {
                uiElement3D.OnLostFocus(new RoutedEventArgs(LostFocusEvent, uiElement3D));
            }
        } 

        ///  
        ///     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 = 
                    UIElement.IsEnabledProperty.AddOwner(
                                typeof(UIElement3D), 
                                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(UIElement.IsEnabledChangedKey, value);} 
            remove {EventHandlersStoreRemove(UIElement.IsEnabledChangedKey, value);}
        }

        ///  
        ///     Fetches the value that IsEnabled should be coerced to.
        ///  
        ///  
        ///     This method is virtual is so that controls derived from UIElement3D
        ///     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 { return true; } } private static object CoerceIsEnabled(DependencyObject d, object value) { UIElement3D uie = (UIElement3D) 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 UIElement3Ds, 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.InternalVisualParent); } if(parent == null || (bool)parent.GetValue(UIElement.IsEnabledProperty)) { return BooleanBoxes.Box(uie.IsEnabledCore); } else { return BooleanBoxes.FalseBox; } } else { return BooleanBoxes.FalseBox; } } private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D)d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(UIElement.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 = UIElement.IsHitTestVisibleProperty.AddOwner( typeof(UIElement3D), 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) { UIElement3D uie = (UIElement3D) 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.InternalVisualParent); 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) { UIElement3D uie = (UIElement3D)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 //********************************************************************* // both _isVisibleMetadata and IsVisibileProperty are constructed in UIElement3D's static constructor private static PropertyMetadata _isVisibleMetadata; /// /// The DependencyProperty for the IsVisible property. /// public static readonly DependencyProperty IsVisibleProperty; /// /// 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 ((UIElement3D)d).IsVisible ? BooleanBoxes.TrueBox : BooleanBoxes.FalseBox; } /// /// IsVisibleChanged event /// public event DependencyPropertyChangedEventHandler IsVisibleChanged { add {EventHandlersStoreAdd(UIElement.IsVisibleChangedKey, value);} remove {EventHandlersStoreRemove(UIElement.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(InternalVisualParent); 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, !isVisible, isVisible)); } } private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D) 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 = UIElement.FocusableProperty.AddOwner( typeof(UIElement3D), 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(UIElement.FocusableChangedKey, value);} remove {EventHandlersStoreRemove(UIElement.FocusableChangedKey, value);} } private static void OnFocusableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D) d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(UIElement.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; } // 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); } } } // 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 // This is called from the force-inherit property changed events. internal static void InvalidateForceInheritPropertyOnChildren(Visual3D v, DependencyProperty property) { int cChildren = v.InternalVisual2DOr3DChildrenCount; for(int iChild = 0; iChild < cChildren; iChild++) { DependencyObject vChild = v.InternalGet2DOr3DVisualChild(iChild); if(vChild != null) { UIElement element = vChild as UIElement; UIElement3D element3D = vChild 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 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. if (vChild is Visual) { UIElement.InvalidateForceInheritPropertyOnChildren((Visual)vChild, property); } else { InvalidateForceInheritPropertyOnChildren((Visual3D)vChild, property); } } } } } #endregion //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields private readonly Visual3DCollection _children; private bool _renderRequestPosted; #endregion Private Fields // 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 AutomationPeerField = new UncommonField(); private bool HasAutomationPeer { get { return ReadFlag(CoreFlags.HasAutomationPeer); } set { WriteFlag(CoreFlags.HasAutomationPeer, 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(); } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // // Copyright (C) Microsoft Corporation. All rights reserved. // // //----------------------------------------------------------------------------- using MS.Internal; using MS.Internal.KnownBoxes; using MS.Internal.Media; using MS.Internal.PresentationCore; using MS.Utility; using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Security; using System.Security.Permissions; using System.Windows.Automation.Peers; using System.Windows.Input; using System.Windows.Input.StylusPlugIns; using System.Windows.Interop; using System.Windows.Markup; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Composition; using System.Windows.Media.Effects; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace System.Windows { /// /// UIElement3D is the base class for frameworks building on the Windows Presentation Core. /// /// /// UIElement3D adds to the base visual class "IFE" - Input, Focus, and Eventing. /// public abstract partial class UIElement3D : Visual3D, IInputElement { /// /// 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 UIElement3D() { UIElement.RegisterEvents(typeof(UIElement3D)); // add owner and then override metadata for IsVisibile IsVisibleProperty = UIElement.IsVisibleProperty.AddOwner(typeof(UIElement3D)); _isVisibleMetadata = new ReadOnlyPropertyMetadata(BooleanBoxes.FalseBox, new GetReadOnlyValueCallback(GetIsVisible), new PropertyChangedCallback(OnIsVisibleChanged)); IsVisibleProperty.OverrideMetadata(typeof(UIElement3D), _isVisibleMetadata, UIElement.IsVisiblePropertyKey); // add owner and then override metadta for IsFocused IsFocusedProperty = UIElement.IsFocusedProperty.AddOwner(typeof(UIElement3D)); IsFocusedProperty.OverrideMetadata(typeof(UIElement3D), new PropertyMetadata( BooleanBoxes.FalseBox, // default value new PropertyChangedCallback(IsFocused_Changed)), UIElement.IsFocusedPropertyKey); } /// /// Constructor. This form of constructor will encounter a slight perf hit since it needs to initialize Dispatcher for the instance. /// protected UIElement3D() { _children = new Visual3DCollection(this); Initialize(); } private void Initialize() { BeginPropertyInitialization(); VisibilityCache = (Visibility) VisibilityProperty.GetDefaultValue(DependencyObjectType); // Note: IsVisibleCache is false by default. // to cause the first render to occur InvalidateModel(); } #region AllowDrop /// /// The DependencyProperty for the AllowDrop property. /// public static readonly DependencyProperty AllowDropProperty = UIElement.AllowDropProperty.AddOwner( typeof(UIElement3D), 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 private object CallRenderCallback(object o) { OnUpdateModel(); _renderRequestPosted = false; return null; } /// /// Invalidates the rendering of the element. /// Causes to be called at a later time. /// public void InvalidateModel() { if(!_renderRequestPosted) { MediaContext.From(Dispatcher).BeginInvokeOnRender(CallRenderCallback, this); _renderRequestPosted = true; } } /// /// This class provides a point for subclasses to access the protected content of the /// UIElement to set what the geometry they should render should be. /// protected virtual void OnUpdateModel() { } /// /// OnVisualParentChanged is called when the parent of the Visual3D is changed. /// /// Old parent or null if the Visual3D did not have a parent before. protected internal override void OnVisualParentChanged(DependencyObject oldParent) { // Synchronize ForceInherit properties if (InternalVisualParent != null) { DependencyObject parent = InternalVisualParent; 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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); } 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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); } } // find a UIElement(3D) ancestor to use for coersion parent = InputElement.GetContainingUIElement(parentAsVisual); } if (parent != null) { UIElement.SynchronizeForceInheritProperties(null, null, this, 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 Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); } else if (oldParent is Visual3D) { ((Visual3D) oldParent).VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(OnVisualAncestorChanged_ForceInherit); } // Try to find a UIElement ancestor to use for coersion. parent = InputElement.GetContainingUIElement(oldParent); } if (parent != null) { UIElement.SynchronizeForceInheritProperties(null, null, this, 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(InternalVisualParent); // 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(InternalVisualParent); 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) { UIElement.SynchronizeForceInheritProperties(null, null, this, parent); } } internal void OnVisualAncestorChanged(object sender, AncestorChangedEventArgs e) { UIElement3D uie3D = sender as UIElement3D; if(null != uie3D) PresentationSource.OnVisualAncestorChanged(uie3D, e); } internal DependencyObject GetUIParent(bool continuePastVisualTree) { return UIElementHelper.GetUIParent(this, continuePastVisualTree); } /// /// 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 internal DependencyObject GetUIParentCore() { // return null; } #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 /// /// 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 Visibility property. /// [CommonDependencyProperty] public static readonly DependencyProperty VisibilityProperty = UIElement.VisibilityProperty.AddOwner( typeof(UIElement3D), new PropertyMetadata( VisibilityBoxes.VisibleBox, new PropertyChangedCallback(OnVisibilityChanged))); private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D) 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() { InternalIsVisible = true; } private void ensureInvisible(bool collapsed) { InternalIsVisible = false; if(!ReadFlag(CoreFlags.IsCollapsed) && collapsed) //Hidden or Visible->Collapsed { WriteFlag(CoreFlags.IsCollapsed, true); } else if(ReadFlag(CoreFlags.IsCollapsed) && !collapsed) //Collapsed -> Hidden { WriteFlag(CoreFlags.IsCollapsed, false); } } // Internal accessor for AccessKeyManager class internal void InvokeAccessKey(AccessKeyEventArgs e) { OnAccessKey(e); } /// /// GotFocus event /// public static readonly RoutedEvent GotFocusEvent = FocusManager.GotFocusEvent.AddOwner(typeof(UIElement3D)); /// /// 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(UIElement3D)); /// /// An event announcing that IsFocused changed to false. /// public event RoutedEventHandler LostFocus { add { AddHandler(LostFocusEvent, value); } remove { RemoveHandler(LostFocusEvent, value); } } /// /// The DependencyProperty for IsFocused. /// Flags: None /// Read-Only: true /// public static readonly DependencyProperty IsFocusedProperty; private static void IsFocused_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uiElement3D = ((UIElement3D)d); if ((bool) e.NewValue) { uiElement3D.OnGotFocus(new RoutedEventArgs(GotFocusEvent, uiElement3D)); } else { uiElement3D.OnLostFocus(new RoutedEventArgs(LostFocusEvent, uiElement3D)); } } /// /// 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 = UIElement.IsEnabledProperty.AddOwner( typeof(UIElement3D), 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(UIElement.IsEnabledChangedKey, value);} remove {EventHandlersStoreRemove(UIElement.IsEnabledChangedKey, value);} } /// /// Fetches the value that IsEnabled should be coerced to. /// /// /// This method is virtual is so that controls derived from UIElement3D /// 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 { return true; } } private static object CoerceIsEnabled(DependencyObject d, object value) { UIElement3D uie = (UIElement3D) 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 UIElement3Ds, 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.InternalVisualParent); } if(parent == null || (bool)parent.GetValue(UIElement.IsEnabledProperty)) { return BooleanBoxes.Box(uie.IsEnabledCore); } else { return BooleanBoxes.FalseBox; } } else { return BooleanBoxes.FalseBox; } } private static void OnIsEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D)d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(UIElement.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 = UIElement.IsHitTestVisibleProperty.AddOwner( typeof(UIElement3D), 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) { UIElement3D uie = (UIElement3D) 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.InternalVisualParent); 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) { UIElement3D uie = (UIElement3D)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 //********************************************************************* // both _isVisibleMetadata and IsVisibileProperty are constructed in UIElement3D's static constructor private static PropertyMetadata _isVisibleMetadata; /// /// The DependencyProperty for the IsVisible property. /// public static readonly DependencyProperty IsVisibleProperty; /// /// 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 ((UIElement3D)d).IsVisible ? BooleanBoxes.TrueBox : BooleanBoxes.FalseBox; } /// /// IsVisibleChanged event /// public event DependencyPropertyChangedEventHandler IsVisibleChanged { add {EventHandlersStoreAdd(UIElement.IsVisibleChangedKey, value);} remove {EventHandlersStoreRemove(UIElement.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(InternalVisualParent); 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, !isVisible, isVisible)); } } private static void OnIsVisibleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D) 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 = UIElement.FocusableProperty.AddOwner( typeof(UIElement3D), 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(UIElement.FocusableChangedKey, value);} remove {EventHandlersStoreRemove(UIElement.FocusableChangedKey, value);} } private static void OnFocusableChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { UIElement3D uie = (UIElement3D) d; // Raise the public changed event. uie.RaiseDependencyPropertyChanged(UIElement.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; } // 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); } } } // 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 // This is called from the force-inherit property changed events. internal static void InvalidateForceInheritPropertyOnChildren(Visual3D v, DependencyProperty property) { int cChildren = v.InternalVisual2DOr3DChildrenCount; for(int iChild = 0; iChild < cChildren; iChild++) { DependencyObject vChild = v.InternalGet2DOr3DVisualChild(iChild); if(vChild != null) { UIElement element = vChild as UIElement; UIElement3D element3D = vChild 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 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. if (vChild is Visual) { UIElement.InvalidateForceInheritPropertyOnChildren((Visual)vChild, property); } else { InvalidateForceInheritPropertyOnChildren((Visual3D)vChild, property); } } } } } #endregion //------------------------------------------------------ // // Private Fields // //----------------------------------------------------- #region Private Fields private readonly Visual3DCollection _children; private bool _renderRequestPosted; #endregion Private Fields // 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 AutomationPeerField = new UncommonField(); private bool HasAutomationPeer { get { return ReadFlag(CoreFlags.HasAutomationPeer); } set { WriteFlag(CoreFlags.HasAutomationPeer, 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(); } } // 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