Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / UIElement3D.cs / 1 / UIElement3D.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.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Effects;
using System.Windows.Media.Media3D;
using System.Windows.Markup;
using System.Windows.Threading;
using System.Windows.Input.StylusPlugIns;
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()
{
RegisterEvents();
// 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
//
// 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 = UIElement3D.PreviewMouseLeftButtonDownEvent;
else if(e.RoutedEvent == Mouse.MouseDownEvent)
newEvent = UIElement3D.MouseLeftButtonDownEvent;
else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent)
newEvent = UIElement3D.PreviewMouseLeftButtonUpEvent;
else
newEvent = UIElement3D.MouseLeftButtonUpEvent;
break;
case MouseButton.Right:
if(e.RoutedEvent == Mouse.PreviewMouseDownEvent)
newEvent = UIElement3D.PreviewMouseRightButtonDownEvent;
else if(e.RoutedEvent == Mouse.MouseDownEvent)
newEvent = UIElement3D.MouseRightButtonDownEvent;
else if(e.RoutedEvent == Mouse.PreviewMouseUpEvent)
newEvent = UIElement3D.PreviewMouseRightButtonUpEvent;
else
newEvent = UIElement3D.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 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

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CurrentTimeZone.cs
- ProcessModuleDesigner.cs
- ParseChildrenAsPropertiesAttribute.cs
- VirtualizingPanel.cs
- WebConfigurationHostFileChange.cs
- ResourceDictionaryCollection.cs
- DependentList.cs
- FunctionDescription.cs
- MsmqChannelFactory.cs
- ObjectQuery.cs
- InheritanceUI.cs
- MenuItemStyle.cs
- ToolStripTemplateNode.cs
- CompilerGeneratedAttribute.cs
- BamlLocalizer.cs
- KnownTypes.cs
- DataIdProcessor.cs
- PackageDigitalSignatureManager.cs
- PrinterResolution.cs
- PaginationProgressEventArgs.cs
- Matrix.cs
- InputReportEventArgs.cs
- OdbcHandle.cs
- TextEditorContextMenu.cs
- CorruptingExceptionCommon.cs
- GridViewUpdatedEventArgs.cs
- comcontractssection.cs
- OverrideMode.cs
- ExpressionParser.cs
- CatalogZone.cs
- DtrList.cs
- InputMethod.cs
- InputBindingCollection.cs
- PrintEvent.cs
- TextAnchor.cs
- WsdlParser.cs
- EmbeddedMailObject.cs
- Int16Animation.cs
- SortFieldComparer.cs
- Schema.cs
- DrawItemEvent.cs
- DefaultConfirmation.cs
- ItemsChangedEventArgs.cs
- RegisteredExpandoAttribute.cs
- WebServiceErrorEvent.cs
- PeerToPeerException.cs
- NotifyInputEventArgs.cs
- TableStyle.cs
- WizardSideBarListControlItemEventArgs.cs
- CustomErrorCollection.cs
- InheritanceAttribute.cs
- CodeExpressionStatement.cs
- AdRotator.cs
- BadImageFormatException.cs
- ToolStripSeparatorRenderEventArgs.cs
- EntityKey.cs
- BuildProviderCollection.cs
- SizeAnimation.cs
- BufferedWebEventProvider.cs
- VerificationAttribute.cs
- Model3DCollection.cs
- RelationshipDetailsCollection.cs
- FolderLevelBuildProvider.cs
- PriorityBinding.cs
- ByeOperationAsyncResult.cs
- ChangeTracker.cs
- UIHelper.cs
- PolyBezierSegmentFigureLogic.cs
- ConsoleKeyInfo.cs
- TreeViewCancelEvent.cs
- DbUpdateCommandTree.cs
- XamlPoint3DCollectionSerializer.cs
- ValueQuery.cs
- WebPartEditVerb.cs
- MessageAction.cs
- Constraint.cs
- FixedSOMSemanticBox.cs
- RecipientInfo.cs
- LockedBorderGlyph.cs
- InsufficientMemoryException.cs
- ViewCellRelation.cs
- XamlTreeBuilder.cs
- NetSectionGroup.cs
- ObjectItemCachedAssemblyLoader.cs
- StringReader.cs
- MetadataPropertyCollection.cs
- ExchangeUtilities.cs
- SmtpLoginAuthenticationModule.cs
- ModifierKeysConverter.cs
- ParameterCollection.cs
- CollectionViewSource.cs
- DirectionalLight.cs
- AutomationPropertyInfo.cs
- StructuralType.cs
- Vector3D.cs
- WebBrowser.cs
- IsolatedStorageFilePermission.cs
- WebPartConnection.cs
- ServicePointManagerElement.cs
- CustomUserNameSecurityTokenAuthenticator.cs