CommandManager.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Input / Command / CommandManager.cs / 1 / CommandManager.cs

                            //---------------------------------------------------------------------------- 
//
//    Copyright (C) Microsoft Corporation.  All rights reserved.
//
//--------------------------------------------------------------------------- 

using System; 
using System.Collections; 
using System.Collections.Generic;
using System.Collections.Specialized; 
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Threading; 
using System.Windows;
using System.Windows.Input; 
using System.Windows.Threading; 
using MS.Internal;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Input 
{
    ///  
    ///     The CommandManager class defines the Commanding Execute/CanExecute Events 
    ///     and also its RoutedEventHandlers which delegates them to corresponding
    ///     ComamndBinding.Execute/CanExecute EventHandlers. 
    /// 
    public sealed class CommandManager
    {
        #region Static Features 

        #region Public Events 
 
        /// 
        ///     Raised when CanExecute should be requeried on commands. 
        ///     Since this event is static, it will only hold onto the handler as a weak reference.
        ///     Users of this event should keep a strong reference to their event handler to avoid
        ///     it being garbage collected. This can be accomplished by having a private field
        ///     and assigning the handler as the value before or after attaching to this event. 
        /// 
        public static event EventHandler RequerySuggested 
        { 
            add { CommandManager.AddWeakReferenceHandler(ref CommandManager.Current._requerySuggestedHandlers, value); }
            remove { CommandManager.RemoveWeakReferenceHandler(CommandManager.Current._requerySuggestedHandlers, value); } 
        }

        /// 
        ///     Event before a command is executed 
        /// 
        public static readonly RoutedEvent PreviewExecutedEvent = 
               EventManager.RegisterRoutedEvent("PreviewExecuted", 
                                                RoutingStrategy.Tunnel,
                                                typeof(ExecutedRoutedEventHandler), 
                                                typeof(CommandManager));

        /// 
        ///     Attaches the handler on the element. 
        /// 
        /// The element on which to attach the handler. 
        /// The handler to attach. 
        public static void AddPreviewExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 
            if (handler == null)
            { 
                throw new ArgumentNullException("handler"); 
            }
 
            element.AddHandler(PreviewExecutedEvent, handler);
        }

        ///  
        ///     Removes the handler from the element.
        ///  
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemovePreviewExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            if (handler == null) 
            { 
                throw new ArgumentNullException("handler");
            } 

            element.RemoveHandler(PreviewExecutedEvent, handler);
        }
 
        /// 
        ///     Event to execute a command 
        ///  
        public static readonly RoutedEvent ExecutedEvent =
                EventManager.RegisterRoutedEvent("Executed", 
                                                 RoutingStrategy.Bubble,
                                                 typeof(ExecutedRoutedEventHandler),
                                                 typeof(CommandManager));
 
        /// 
        ///     Attaches the handler on the element. 
        ///  
        /// The element on which to attach the handler.
        /// The handler to attach. 
        public static void AddExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            if (handler == null) 
            {
                throw new ArgumentNullException("handler"); 
            }

            element.AddHandler(ExecutedEvent, handler);
        } 

        ///  
        ///     Removes the handler from the element. 
        /// 
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemoveExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 
            if (handler == null)
            { 
                throw new ArgumentNullException("handler");
            }

            element.RemoveHandler(ExecutedEvent, handler); 
        }
 
        ///  
        ///     Event to determine if a command can be executed
        ///  
        public static readonly RoutedEvent PreviewCanExecuteEvent =
                EventManager.RegisterRoutedEvent("PreviewCanExecute",
                                                 RoutingStrategy.Tunnel,
                                                 typeof(CanExecuteRoutedEventHandler), 
                                                 typeof(CommandManager));
 
        ///  
        ///     Attaches the handler on the element.
        ///  
        /// The element on which to attach the handler.
        /// The handler to attach.
        public static void AddPreviewCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
            if (handler == null) 
            {
                throw new ArgumentNullException("handler");
            }
 
            element.AddHandler(PreviewCanExecuteEvent, handler);
        } 
 
        /// 
        ///     Removes the handler from the element. 
        /// 
        /// The element from which to remove the handler.
        /// The handler to remove.
        public static void RemovePreviewCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            } 

            element.RemoveHandler(PreviewCanExecuteEvent, handler); 
        } 

        ///  
        ///     Event to determine if a command can be executed
        /// 
        public static readonly RoutedEvent CanExecuteEvent =
                EventManager.RegisterRoutedEvent("CanExecute", 
                                                 RoutingStrategy.Bubble,
                                                 typeof(CanExecuteRoutedEventHandler), 
                                                 typeof(CommandManager)); 

        ///  
        ///     Attaches the handler on the element.
        /// 
        /// The element on which to attach the handler.
        /// The handler to attach. 
        public static void AddCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler"); 
            }
 
            element.AddHandler(CanExecuteEvent, handler); 
        }
 
        /// 
        ///     Removes the handler from the element.
        /// 
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemoveCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            if (handler == null)
            { 
                throw new ArgumentNullException("handler");
            } 
 
            element.RemoveHandler(CanExecuteEvent, handler);
        } 

        #endregion

        #region Public Methods 

        ///  
        ///     Register class level InputBindings. 
        /// 
        /// Owner type 
        /// InputBinding to register
        public static void RegisterClassInputBinding(Type type, InputBinding inputBinding)
        {
            if (type == null) 
            {
                throw new ArgumentNullException("type"); 
            } 
            if (inputBinding == null)
            { 
                throw new ArgumentNullException("inputBinding");
            }

            lock (_classInputBindings.SyncRoot) 
            {
                InputBindingCollection inputBindings = _classInputBindings[type] as InputBindingCollection; 
 
                if (inputBindings == null)
                { 
                    inputBindings = new InputBindingCollection();
                    _classInputBindings[type] = inputBindings;
                }
 
                inputBindings.Add(inputBinding);
            } 
        } 

        ///  
        ///     Register class level CommandBindings.
        /// 
        /// Owner type
        /// CommandBinding to register 
        public static void RegisterClassCommandBinding(Type type, CommandBinding commandBinding)
        { 
            if (type == null) 
            {
                throw new ArgumentNullException("type"); 
            }
            if (commandBinding == null)
            {
                throw new ArgumentNullException("commandBinding"); 
            }
 
            lock (_classCommandBindings.SyncRoot) 
            {
                CommandBindingCollection bindings = _classCommandBindings[type] as CommandBindingCollection; 

                if (bindings == null)
                {
                    bindings = new CommandBindingCollection(); 
                    _classCommandBindings[type] = bindings;
                } 
 
                bindings.Add(commandBinding);
            } 
        }

        /// 
        ///     Invokes RequerySuggested listeners registered on the current thread. 
        /// 
        public static void InvalidateRequerySuggested() 
        { 
            CommandManager.Current.RaiseRequerySuggested();
        } 

        #endregion

        #region Implementation 

        ///  
        ///     Return the CommandManager associated with the current thread. 
        /// 
        private static CommandManager Current 
        {
            get
            {
                if (_commandManager == null) 
                {
                    _commandManager = new CommandManager(); 
                } 

                return _commandManager; 
            }
        }

        ///  
        ///     Scans input and command bindings for matching gestures and executes the appropriate command
        ///  
        ///  
        ///     Scans for command to execute in the following order:
        ///     - input bindings associated with the targetElement instance 
        ///     - input bindings associated with the targetElement class
        ///     - command bindings associated with the targetElement instance
        ///     - command bindings associated with the targetElement class
        ///  
        /// UIElement/ContentElement to be scanned for input and command bindings
        /// InputEventArgs to be matched against for gestures 
        ///  
        ///     Critical: This code can be used to spoof input and cause elevations for Userinitiated paste
        ///  
        [SecurityCritical]
        internal static void TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
        {
            if ((targetElement == null) || (inputEventArgs == null)) 
            {
                return; 
            } 

            ICommand command = null; 
            IInputElement target = null;
            object parameter = null;

            // Determine UIElement/ContentElement/Neither type 
            DependencyObject targetElementAsDO = targetElement as DependencyObject;
            bool isUIElement = InputElement.IsUIElement(targetElementAsDO); 
            bool isContentElement = !isUIElement && InputElement.IsContentElement(targetElementAsDO); 
            bool isUIElement3D = !isUIElement && !isContentElement && InputElement.IsUIElement3D(targetElementAsDO);
 
            // Step 1: Check local input bindings
            InputBindingCollection localInputBindings = null;
            if (isUIElement)
            { 
                localInputBindings = ((UIElement)targetElement).InputBindingsInternal;
            } 
            else if (isContentElement) 
            {
                localInputBindings = ((ContentElement)targetElement).InputBindingsInternal; 
            }
            else if (isUIElement3D)
            {
                localInputBindings = ((UIElement3D)targetElement).InputBindingsInternal; 
            }
            if (localInputBindings != null) 
            { 
                InputBinding inputBinding = localInputBindings.FindMatch(targetElement, inputEventArgs);
                if (inputBinding != null) 
                {
                    command = inputBinding.Command;
                    target = inputBinding.CommandTarget;
                    parameter = inputBinding.CommandParameter; 
                }
            } 
 
            // Step 2: If no command, check class input bindings
            if (command == null) 
            {
                lock (_classInputBindings.SyncRoot)
                {
                    Type classType = targetElement.GetType(); 
                    while (classType != null)
                    { 
                        InputBindingCollection classInputBindings = _classInputBindings[classType] as InputBindingCollection; 
                        if (classInputBindings != null)
                        { 
                            InputBinding inputBinding = classInputBindings.FindMatch(targetElement, inputEventArgs);
                            if (inputBinding != null)
                            {
                                command = inputBinding.Command; 
                                target = inputBinding.CommandTarget;
                                parameter = inputBinding.CommandParameter; 
                                break; 
                            }
                        } 
                        classType = classType.BaseType;
                    }
                }
            } 

            // Step 3: If no command, check local command bindings 
            if (command == null) 
            {
                // Check for the instance level ones Next 
                CommandBindingCollection localCommandBindings = null;
                if (isUIElement)
                {
                    localCommandBindings = ((UIElement)targetElement).CommandBindingsInternal; 
                }
                else if (isContentElement) 
                { 
                    localCommandBindings = ((ContentElement)targetElement).CommandBindingsInternal;
                } 
                else if (isUIElement3D)
                {
                    localCommandBindings = ((UIElement3D)targetElement).CommandBindingsInternal;
                } 
                if (localCommandBindings != null)
                { 
                    command = localCommandBindings.FindMatch(targetElement, inputEventArgs); 
                }
            } 

            // Step 4: If no command, look at class command bindings
            if (command == null)
            { 
                lock (_classCommandBindings.SyncRoot)
                { 
                    Type classType = targetElement.GetType(); 
                    while (classType != null)
                    { 
                        CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection;
                        if (classCommandBindings != null)
                        {
                            command = classCommandBindings.FindMatch(targetElement, inputEventArgs); 
                            if (command != null)
                            { 
                                break; 
                            }
                        } 
                        classType = classType.BaseType;
                    }
                }
            } 

            // Step 5: If found a command, then execute it (unless it is 
            // the special "NotACommand" command, which we simply ignore without 
            // setting Handled=true, so that the input bubbles up to the parent)
            if (command != null && command != ApplicationCommands.NotACommand) 
            {
                // We currently do not support declaring the element with focus as the target
                // element by setting target == null.  Instead, we interpret a null target to indicate
                // the element that we are routing the event through, e.g. the targetElement parameter. 
                if (target == null)
                { 
                    target = targetElement; 
                }
 
                bool continueRouting = false;

                RoutedCommand routedCommand = command as RoutedCommand;
                if (routedCommand != null) 
                {
                    if (routedCommand.CriticalCanExecute(parameter, 
                                                    target, 
                                                    inputEventArgs.UserInitiated /*trusted*/,
                                                    out continueRouting)) 
                    {
                        ExecuteCommand(routedCommand, parameter, target, inputEventArgs);
                    }
                } 
                else
                { 
                    if (command.CanExecute(parameter)) 
                    {
                        command.Execute(parameter); 
                    }
                }

                // If we mapped an input event to a command, we should always 
                // handle the input event - regardless of whether the command
                // was executed or not.  Unless the CanExecute handler told us 
                // to continue the route. 
                inputEventArgs.Handled = !continueRouting;
            } 
        }

        /// 
        ///     Critical - accesses critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information, does not modify)
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private static bool ExecuteCommand(RoutedCommand routedCommand, object parameter, IInputElement target, InputEventArgs inputEventArgs)
        { 
            return routedCommand.ExecuteCore(parameter, target, inputEventArgs.UserInitiated);
        }

        ///  
        ///     Forwards CanExecute events to CommandBindings.
        ///  
        internal static void OnCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if ((sender != null) && (e != null) && (e.Command != null)) 
            {
                FindCommandBinding(sender, e, e.Command, false);

                if (!e.Handled && (e.RoutedEvent == CanExecuteEvent)) 
                {
                    DependencyObject d = sender as DependencyObject; 
                    if (d != null) 
                    {
                        if (FocusManager.GetIsFocusScope(d)) 
                        {
                            // This element is a focus scope.
                            // Try to transfer the event to its parent focus scope's focused element.
                            IInputElement focusedElement = GetParentScopeFocusedElement(d); 
                            if (focusedElement != null)
                            { 
                                TransferEvent(focusedElement, e); 
                            }
                        } 
                    }
                }
            }
        } 

        private static bool CanExecuteCommandBinding(object sender, CanExecuteRoutedEventArgs e, CommandBinding commandBinding) 
        { 
            commandBinding.OnCanExecute(sender, e);
            return e.CanExecute || e.Handled; 
        }

        /// 
        ///     Forwards Executed events to CommandBindings. 
        /// 
        internal static void OnExecuted(object sender, ExecutedRoutedEventArgs e) 
        { 
            if ((sender != null) && (e != null) && (e.Command != null))
            { 
                FindCommandBinding(sender, e, e.Command, true);

                if (!e.Handled && (e.RoutedEvent == ExecutedEvent))
                { 
                    DependencyObject d = sender as DependencyObject;
                    if (d != null) 
                    { 
                        if (FocusManager.GetIsFocusScope(d))
                        { 
                            // This element is a focus scope.
                            // Try to transfer the event to its parent focus scope's focused element.
                            IInputElement focusedElement = GetParentScopeFocusedElement(d);
                            if (focusedElement != null) 
                            {
                                TransferEvent(focusedElement, e); 
                            } 
                        }
                    } 
                }
            }
        }
 
        /// 
        ///     Critical - creates critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information) 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private static bool ExecuteCommandBinding(object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
        {
            // Asserting a permission in the case that the command was user initiated
            // and the command is a secure command. We can do this safely because at 
            // the time the binding was setup, we demanded the permission.
            ISecureCommand secureCommand = e.Command as ISecureCommand; 
            bool elevate = e.UserInitiated && (secureCommand != null) && (secureCommand.UserInitiatedPermission != null); 

            if (elevate) 
            {
                secureCommand.UserInitiatedPermission.Assert(); //BlessedAssert
            }
            try 
            {
                commandBinding.OnExecuted(sender, e); 
            } 
            finally
            { 
                if (elevate)
                {
                    CodeAccessPermission.RevertAssert();
                } 
            }
 
            return e.Handled; 
        }
 
        internal static void OnCommandDevice(object sender, CommandDeviceEventArgs e)
        {
            if ((sender != null) && (e != null) && (e.Command != null))
            { 
                CanExecuteRoutedEventArgs canExecuteArgs = new CanExecuteRoutedEventArgs(e.Command, null /* parameter */);
                canExecuteArgs.RoutedEvent = CommandManager.CanExecuteEvent; 
                canExecuteArgs.Source = sender; 
                OnCanExecute(sender, canExecuteArgs);
 
                if (canExecuteArgs.CanExecute)
                {
                    ExecutedRoutedEventArgs executedArgs = new ExecutedRoutedEventArgs(e.Command, null /* parameter */);
                    executedArgs.RoutedEvent = CommandManager.ExecutedEvent; 
                    executedArgs.Source = sender;
                    OnExecuted(sender, executedArgs); 
 
                    if (executedArgs.Handled)
                    { 
                        e.Handled = true;
                    }
                }
            } 
        }
 
        private static void FindCommandBinding(object sender, RoutedEventArgs e, ICommand command, bool execute) 
        {
            // Check local command bindings 
            CommandBindingCollection commandBindings = null;
            DependencyObject senderAsDO = sender as DependencyObject;
            if (InputElement.IsUIElement(senderAsDO))
            { 
                commandBindings = ((UIElement)senderAsDO).CommandBindingsInternal;
            } 
            else if (InputElement.IsContentElement(senderAsDO)) 
            {
                commandBindings = ((ContentElement)senderAsDO).CommandBindingsInternal; 
            }
            else if (InputElement.IsUIElement3D(senderAsDO))
            {
                commandBindings = ((UIElement3D)senderAsDO).CommandBindingsInternal; 
            }
            if (commandBindings != null) 
            { 
                FindCommandBinding(commandBindings, sender, e, command, execute);
            } 

            // If no command binding is found, check class command bindings
            lock (_classCommandBindings.SyncRoot)
            { 
                // Check from the current type to all the base types
                Type classType = sender.GetType(); 
                while (classType != null) 
                {
                    CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection; 
                    if (classCommandBindings != null)
                    {
                        FindCommandBinding(classCommandBindings, sender, e, command, execute);
                    } 
                    classType = classType.BaseType;
                } 
            } 
        }
 
        private static void FindCommandBinding(CommandBindingCollection commandBindings, object sender, RoutedEventArgs e, ICommand command, bool execute)
        {
            int index = 0;
            while (true) 
            {
                CommandBinding commandBinding = commandBindings.FindMatch(command, ref index); 
                if ((commandBinding == null) || 
                    (execute && ExecuteCommandBinding(sender, (ExecutedRoutedEventArgs)e, commandBinding)) ||
                    (!execute && CanExecuteCommandBinding(sender, (CanExecuteRoutedEventArgs)e, commandBinding))) 
                {
                    break;
                }
            } 
        }
 
        private static void TransferEvent(IInputElement newSource, CanExecuteRoutedEventArgs e) 
        {
            RoutedCommand command = e.Command as RoutedCommand; 
            if (command != null)
            {
                try
                { 
                    e.CanExecute = command.CanExecute(e.Parameter, newSource);
                } 
                finally 
                {
                    e.Handled = true; 
                }
            }
        }
 
        /// 
        ///     Critical - creates critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information) 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private static void TransferEvent(IInputElement newSource, ExecutedRoutedEventArgs e)
        {
            RoutedCommand command = e.Command as RoutedCommand;
            if (command != null) 
            {
                try 
                { 
                    // SecurityCritical: Must not modify UserInitiated
                    command.ExecuteCore(e.Parameter, newSource, e.UserInitiated); 
                }
                finally
                {
                    e.Handled = true; 
                }
            } 
        } 

        private static IInputElement GetParentScopeFocusedElement(DependencyObject childScope) 
        {
            DependencyObject parentScope = GetParentScope(childScope);
            if (parentScope != null)
            { 
                IInputElement focusedElement = FocusManager.GetFocusedElement(parentScope);
                if ((focusedElement != null) && !ContainsElement(childScope, focusedElement as DependencyObject)) 
                { 
                    // The focused element from the parent focus scope is not within the focus scope
                    // of the current element. 
                    return focusedElement;
                }
            }
 
            return null;
        } 
 
        private static DependencyObject GetParentScope(DependencyObject childScope)
        { 
            // Get the parent element of the childScope element
            DependencyObject parent = null;
            UIElement element = childScope as UIElement;
            ContentElement contentElement = (element == null) ? childScope as ContentElement : null; 
            UIElement3D element3D = (element == null && contentElement == null) ? childScope as UIElement3D : null;
 
            if (element != null) 
            {
                parent = element.GetUIParent(true); 
            }
            else if (contentElement != null)
            {
                parent = contentElement.GetUIParent(true); 
            }
            else if (element3D != null) 
            { 
                parent = element3D.GetUIParent(true);
            } 

            if (parent != null)
            {
                // Get the next focus scope above this one 
                return FocusManager.GetFocusScope(parent);
            } 
 
            return null;
        } 

        private static bool ContainsElement(DependencyObject scope, DependencyObject child)
        {
            if (child != null) 
            {
                DependencyObject parentScope = FocusManager.GetFocusScope(child); 
                while (parentScope != null) 
                {
                    if (parentScope == scope) 
                    {
                        // A parent scope matches the scope we are looking for
                        return true;
                    } 
                    parentScope = GetParentScope(parentScope);
                } 
            } 

            return false; 
        }

        #endregion
 
        #region Data
 
        // The CommandManager associated with the current thread 
        [ThreadStatic]
        private static CommandManager _commandManager; 

        // This is a Hashtable of CommandBindingCollections keyed on OwnerType
        // Each ItemList holds the registered Class level CommandBindings for that OwnerType
        private static HybridDictionary _classCommandBindings = new HybridDictionary(); 

        // This is a Hashtable of InputBindingCollections keyed on OwnerType 
        // Each Item holds the registered Class level CommandBindings for that OwnerType 
        private static HybridDictionary _classInputBindings = new HybridDictionary();
 
        #endregion

        #endregion
 
        #region Instance Features
 
        #region Constructor 

        /// 
        ///     Creates a new instance of this class.
        ///
        private CommandManager()
        { 
        }
 
        #endregion 

        #region Implementation 

        /// 
        ///     Adds an idle priority dispatcher operation to raise RequerySuggested.
        ///  
        private void RaiseRequerySuggested()
        { 
            if (_requerySuggestedOperation == null) 
            {
                Dispatcher dispatcher = Dispatcher.CurrentDispatcher; 
                if ((dispatcher != null) && !dispatcher.HasShutdownStarted && !dispatcher.HasShutdownFinished)
                {
                    _requerySuggestedOperation = dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(RaiseRequerySuggested), null);
                } 
            }
        } 
 
        private object RaiseRequerySuggested(object obj)
        { 
            // Call the RequerySuggested handlers
            _requerySuggestedOperation = null;
            CommandManager.CallWeakReferenceHandlers(_requerySuggestedHandlers);
            return null; 
        }
 
        internal static void CallWeakReferenceHandlers(List handlers) 
        {
            if (handlers != null) 
            {
                // Take a snapshot of the handlers before we call out to them since the handlers
                // could cause the array to me modified while we are reading it.
 
                EventHandler[] callees = new EventHandler[handlers.Count];
                int count = 0; 
 
                for (int i = handlers.Count - 1; i >= 0; i--)
                { 
                    WeakReference reference = handlers[i];
                    EventHandler handler = reference.Target as EventHandler;
                    if (handler == null)
                    { 
                        // Clean up old handlers that have been collected
                        handlers.RemoveAt(i); 
                    } 
                    else
                    { 
                        callees[count] = handler;
                        count++;
                    }
                } 

                // Call the handlers that we snapshotted 
                for (int i = 0; i < count; i++) 
                {
                    EventHandler handler = callees[i]; 
                    handler(null, EventArgs.Empty);
                }
            }
        } 

        internal static void AddWeakReferenceHandler(ref List handlers, EventHandler handler) 
        { 
            if (handlers == null)
            { 
                handlers = new List();
            }

            handlers.Add(new WeakReference(handler)); 
        }
 
        internal static void RemoveWeakReferenceHandler(List handlers, EventHandler handler) 
        {
            if (handlers != null) 
            {
                for (int i = handlers.Count - 1; i >= 0; i--)
                {
                    WeakReference reference = handlers[i]; 
                    EventHandler existingHandler = reference.Target as EventHandler;
                    if ((existingHandler == null) || (existingHandler == handler)) 
                    { 
                        // Clean up old handlers that have been collected
                        // in addition to the handler that is to be removed. 
                        handlers.RemoveAt(i);
                    }
                }
            } 
        }
 
        #endregion 

        #region Data 

        // This is the event we fire when told to InvalidateStatus
        private List _requerySuggestedHandlers;
 
        // An operation object indicating that a callback is already on the dispatcher
        private DispatcherOperation _requerySuggestedOperation = null; 
 
        #endregion
 
        #endregion
    }
}

// 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 System; 
using System.Collections; 
using System.Collections.Generic;
using System.Collections.Specialized; 
using System.Diagnostics;
using System.Security;
using System.Security.Permissions;
using System.Threading; 
using System.Windows;
using System.Windows.Input; 
using System.Windows.Threading; 
using MS.Internal;
 
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;

namespace System.Windows.Input 
{
    ///  
    ///     The CommandManager class defines the Commanding Execute/CanExecute Events 
    ///     and also its RoutedEventHandlers which delegates them to corresponding
    ///     ComamndBinding.Execute/CanExecute EventHandlers. 
    /// 
    public sealed class CommandManager
    {
        #region Static Features 

        #region Public Events 
 
        /// 
        ///     Raised when CanExecute should be requeried on commands. 
        ///     Since this event is static, it will only hold onto the handler as a weak reference.
        ///     Users of this event should keep a strong reference to their event handler to avoid
        ///     it being garbage collected. This can be accomplished by having a private field
        ///     and assigning the handler as the value before or after attaching to this event. 
        /// 
        public static event EventHandler RequerySuggested 
        { 
            add { CommandManager.AddWeakReferenceHandler(ref CommandManager.Current._requerySuggestedHandlers, value); }
            remove { CommandManager.RemoveWeakReferenceHandler(CommandManager.Current._requerySuggestedHandlers, value); } 
        }

        /// 
        ///     Event before a command is executed 
        /// 
        public static readonly RoutedEvent PreviewExecutedEvent = 
               EventManager.RegisterRoutedEvent("PreviewExecuted", 
                                                RoutingStrategy.Tunnel,
                                                typeof(ExecutedRoutedEventHandler), 
                                                typeof(CommandManager));

        /// 
        ///     Attaches the handler on the element. 
        /// 
        /// The element on which to attach the handler. 
        /// The handler to attach. 
        public static void AddPreviewExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        { 
            if (element == null)
            {
                throw new ArgumentNullException("element");
            } 
            if (handler == null)
            { 
                throw new ArgumentNullException("handler"); 
            }
 
            element.AddHandler(PreviewExecutedEvent, handler);
        }

        ///  
        ///     Removes the handler from the element.
        ///  
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemovePreviewExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler) 
        {
            if (element == null)
            {
                throw new ArgumentNullException("element"); 
            }
            if (handler == null) 
            { 
                throw new ArgumentNullException("handler");
            } 

            element.RemoveHandler(PreviewExecutedEvent, handler);
        }
 
        /// 
        ///     Event to execute a command 
        ///  
        public static readonly RoutedEvent ExecutedEvent =
                EventManager.RegisterRoutedEvent("Executed", 
                                                 RoutingStrategy.Bubble,
                                                 typeof(ExecutedRoutedEventHandler),
                                                 typeof(CommandManager));
 
        /// 
        ///     Attaches the handler on the element. 
        ///  
        /// The element on which to attach the handler.
        /// The handler to attach. 
        public static void AddExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        {
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            } 
            if (handler == null) 
            {
                throw new ArgumentNullException("handler"); 
            }

            element.AddHandler(ExecutedEvent, handler);
        } 

        ///  
        ///     Removes the handler from the element. 
        /// 
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemoveExecutedHandler(UIElement element, ExecutedRoutedEventHandler handler)
        {
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            } 
            if (handler == null)
            { 
                throw new ArgumentNullException("handler");
            }

            element.RemoveHandler(ExecutedEvent, handler); 
        }
 
        ///  
        ///     Event to determine if a command can be executed
        ///  
        public static readonly RoutedEvent PreviewCanExecuteEvent =
                EventManager.RegisterRoutedEvent("PreviewCanExecute",
                                                 RoutingStrategy.Tunnel,
                                                 typeof(CanExecuteRoutedEventHandler), 
                                                 typeof(CommandManager));
 
        ///  
        ///     Attaches the handler on the element.
        ///  
        /// The element on which to attach the handler.
        /// The handler to attach.
        public static void AddPreviewCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler)
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element"); 
            }
            if (handler == null) 
            {
                throw new ArgumentNullException("handler");
            }
 
            element.AddHandler(PreviewCanExecuteEvent, handler);
        } 
 
        /// 
        ///     Removes the handler from the element. 
        /// 
        /// The element from which to remove the handler.
        /// The handler to remove.
        public static void RemovePreviewCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler) 
        {
            if (element == null) 
            { 
                throw new ArgumentNullException("element");
            } 
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            } 

            element.RemoveHandler(PreviewCanExecuteEvent, handler); 
        } 

        ///  
        ///     Event to determine if a command can be executed
        /// 
        public static readonly RoutedEvent CanExecuteEvent =
                EventManager.RegisterRoutedEvent("CanExecute", 
                                                 RoutingStrategy.Bubble,
                                                 typeof(CanExecuteRoutedEventHandler), 
                                                 typeof(CommandManager)); 

        ///  
        ///     Attaches the handler on the element.
        /// 
        /// The element on which to attach the handler.
        /// The handler to attach. 
        public static void AddCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler)
        { 
            if (element == null) 
            {
                throw new ArgumentNullException("element"); 
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler"); 
            }
 
            element.AddHandler(CanExecuteEvent, handler); 
        }
 
        /// 
        ///     Removes the handler from the element.
        /// 
        /// The element from which to remove the handler. 
        /// The handler to remove.
        public static void RemoveCanExecuteHandler(UIElement element, CanExecuteRoutedEventHandler handler) 
        { 
            if (element == null)
            { 
                throw new ArgumentNullException("element");
            }
            if (handler == null)
            { 
                throw new ArgumentNullException("handler");
            } 
 
            element.RemoveHandler(CanExecuteEvent, handler);
        } 

        #endregion

        #region Public Methods 

        ///  
        ///     Register class level InputBindings. 
        /// 
        /// Owner type 
        /// InputBinding to register
        public static void RegisterClassInputBinding(Type type, InputBinding inputBinding)
        {
            if (type == null) 
            {
                throw new ArgumentNullException("type"); 
            } 
            if (inputBinding == null)
            { 
                throw new ArgumentNullException("inputBinding");
            }

            lock (_classInputBindings.SyncRoot) 
            {
                InputBindingCollection inputBindings = _classInputBindings[type] as InputBindingCollection; 
 
                if (inputBindings == null)
                { 
                    inputBindings = new InputBindingCollection();
                    _classInputBindings[type] = inputBindings;
                }
 
                inputBindings.Add(inputBinding);
            } 
        } 

        ///  
        ///     Register class level CommandBindings.
        /// 
        /// Owner type
        /// CommandBinding to register 
        public static void RegisterClassCommandBinding(Type type, CommandBinding commandBinding)
        { 
            if (type == null) 
            {
                throw new ArgumentNullException("type"); 
            }
            if (commandBinding == null)
            {
                throw new ArgumentNullException("commandBinding"); 
            }
 
            lock (_classCommandBindings.SyncRoot) 
            {
                CommandBindingCollection bindings = _classCommandBindings[type] as CommandBindingCollection; 

                if (bindings == null)
                {
                    bindings = new CommandBindingCollection(); 
                    _classCommandBindings[type] = bindings;
                } 
 
                bindings.Add(commandBinding);
            } 
        }

        /// 
        ///     Invokes RequerySuggested listeners registered on the current thread. 
        /// 
        public static void InvalidateRequerySuggested() 
        { 
            CommandManager.Current.RaiseRequerySuggested();
        } 

        #endregion

        #region Implementation 

        ///  
        ///     Return the CommandManager associated with the current thread. 
        /// 
        private static CommandManager Current 
        {
            get
            {
                if (_commandManager == null) 
                {
                    _commandManager = new CommandManager(); 
                } 

                return _commandManager; 
            }
        }

        ///  
        ///     Scans input and command bindings for matching gestures and executes the appropriate command
        ///  
        ///  
        ///     Scans for command to execute in the following order:
        ///     - input bindings associated with the targetElement instance 
        ///     - input bindings associated with the targetElement class
        ///     - command bindings associated with the targetElement instance
        ///     - command bindings associated with the targetElement class
        ///  
        /// UIElement/ContentElement to be scanned for input and command bindings
        /// InputEventArgs to be matched against for gestures 
        ///  
        ///     Critical: This code can be used to spoof input and cause elevations for Userinitiated paste
        ///  
        [SecurityCritical]
        internal static void TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
        {
            if ((targetElement == null) || (inputEventArgs == null)) 
            {
                return; 
            } 

            ICommand command = null; 
            IInputElement target = null;
            object parameter = null;

            // Determine UIElement/ContentElement/Neither type 
            DependencyObject targetElementAsDO = targetElement as DependencyObject;
            bool isUIElement = InputElement.IsUIElement(targetElementAsDO); 
            bool isContentElement = !isUIElement && InputElement.IsContentElement(targetElementAsDO); 
            bool isUIElement3D = !isUIElement && !isContentElement && InputElement.IsUIElement3D(targetElementAsDO);
 
            // Step 1: Check local input bindings
            InputBindingCollection localInputBindings = null;
            if (isUIElement)
            { 
                localInputBindings = ((UIElement)targetElement).InputBindingsInternal;
            } 
            else if (isContentElement) 
            {
                localInputBindings = ((ContentElement)targetElement).InputBindingsInternal; 
            }
            else if (isUIElement3D)
            {
                localInputBindings = ((UIElement3D)targetElement).InputBindingsInternal; 
            }
            if (localInputBindings != null) 
            { 
                InputBinding inputBinding = localInputBindings.FindMatch(targetElement, inputEventArgs);
                if (inputBinding != null) 
                {
                    command = inputBinding.Command;
                    target = inputBinding.CommandTarget;
                    parameter = inputBinding.CommandParameter; 
                }
            } 
 
            // Step 2: If no command, check class input bindings
            if (command == null) 
            {
                lock (_classInputBindings.SyncRoot)
                {
                    Type classType = targetElement.GetType(); 
                    while (classType != null)
                    { 
                        InputBindingCollection classInputBindings = _classInputBindings[classType] as InputBindingCollection; 
                        if (classInputBindings != null)
                        { 
                            InputBinding inputBinding = classInputBindings.FindMatch(targetElement, inputEventArgs);
                            if (inputBinding != null)
                            {
                                command = inputBinding.Command; 
                                target = inputBinding.CommandTarget;
                                parameter = inputBinding.CommandParameter; 
                                break; 
                            }
                        } 
                        classType = classType.BaseType;
                    }
                }
            } 

            // Step 3: If no command, check local command bindings 
            if (command == null) 
            {
                // Check for the instance level ones Next 
                CommandBindingCollection localCommandBindings = null;
                if (isUIElement)
                {
                    localCommandBindings = ((UIElement)targetElement).CommandBindingsInternal; 
                }
                else if (isContentElement) 
                { 
                    localCommandBindings = ((ContentElement)targetElement).CommandBindingsInternal;
                } 
                else if (isUIElement3D)
                {
                    localCommandBindings = ((UIElement3D)targetElement).CommandBindingsInternal;
                } 
                if (localCommandBindings != null)
                { 
                    command = localCommandBindings.FindMatch(targetElement, inputEventArgs); 
                }
            } 

            // Step 4: If no command, look at class command bindings
            if (command == null)
            { 
                lock (_classCommandBindings.SyncRoot)
                { 
                    Type classType = targetElement.GetType(); 
                    while (classType != null)
                    { 
                        CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection;
                        if (classCommandBindings != null)
                        {
                            command = classCommandBindings.FindMatch(targetElement, inputEventArgs); 
                            if (command != null)
                            { 
                                break; 
                            }
                        } 
                        classType = classType.BaseType;
                    }
                }
            } 

            // Step 5: If found a command, then execute it (unless it is 
            // the special "NotACommand" command, which we simply ignore without 
            // setting Handled=true, so that the input bubbles up to the parent)
            if (command != null && command != ApplicationCommands.NotACommand) 
            {
                // We currently do not support declaring the element with focus as the target
                // element by setting target == null.  Instead, we interpret a null target to indicate
                // the element that we are routing the event through, e.g. the targetElement parameter. 
                if (target == null)
                { 
                    target = targetElement; 
                }
 
                bool continueRouting = false;

                RoutedCommand routedCommand = command as RoutedCommand;
                if (routedCommand != null) 
                {
                    if (routedCommand.CriticalCanExecute(parameter, 
                                                    target, 
                                                    inputEventArgs.UserInitiated /*trusted*/,
                                                    out continueRouting)) 
                    {
                        ExecuteCommand(routedCommand, parameter, target, inputEventArgs);
                    }
                } 
                else
                { 
                    if (command.CanExecute(parameter)) 
                    {
                        command.Execute(parameter); 
                    }
                }

                // If we mapped an input event to a command, we should always 
                // handle the input event - regardless of whether the command
                // was executed or not.  Unless the CanExecute handler told us 
                // to continue the route. 
                inputEventArgs.Handled = !continueRouting;
            } 
        }

        /// 
        ///     Critical - accesses critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information, does not modify)
        ///  
        [SecurityCritical, SecurityTreatAsSafe] 
        private static bool ExecuteCommand(RoutedCommand routedCommand, object parameter, IInputElement target, InputEventArgs inputEventArgs)
        { 
            return routedCommand.ExecuteCore(parameter, target, inputEventArgs.UserInitiated);
        }

        ///  
        ///     Forwards CanExecute events to CommandBindings.
        ///  
        internal static void OnCanExecute(object sender, CanExecuteRoutedEventArgs e) 
        {
            if ((sender != null) && (e != null) && (e.Command != null)) 
            {
                FindCommandBinding(sender, e, e.Command, false);

                if (!e.Handled && (e.RoutedEvent == CanExecuteEvent)) 
                {
                    DependencyObject d = sender as DependencyObject; 
                    if (d != null) 
                    {
                        if (FocusManager.GetIsFocusScope(d)) 
                        {
                            // This element is a focus scope.
                            // Try to transfer the event to its parent focus scope's focused element.
                            IInputElement focusedElement = GetParentScopeFocusedElement(d); 
                            if (focusedElement != null)
                            { 
                                TransferEvent(focusedElement, e); 
                            }
                        } 
                    }
                }
            }
        } 

        private static bool CanExecuteCommandBinding(object sender, CanExecuteRoutedEventArgs e, CommandBinding commandBinding) 
        { 
            commandBinding.OnCanExecute(sender, e);
            return e.CanExecute || e.Handled; 
        }

        /// 
        ///     Forwards Executed events to CommandBindings. 
        /// 
        internal static void OnExecuted(object sender, ExecutedRoutedEventArgs e) 
        { 
            if ((sender != null) && (e != null) && (e.Command != null))
            { 
                FindCommandBinding(sender, e, e.Command, true);

                if (!e.Handled && (e.RoutedEvent == ExecutedEvent))
                { 
                    DependencyObject d = sender as DependencyObject;
                    if (d != null) 
                    { 
                        if (FocusManager.GetIsFocusScope(d))
                        { 
                            // This element is a focus scope.
                            // Try to transfer the event to its parent focus scope's focused element.
                            IInputElement focusedElement = GetParentScopeFocusedElement(d);
                            if (focusedElement != null) 
                            {
                                TransferEvent(focusedElement, e); 
                            } 
                        }
                    } 
                }
            }
        }
 
        /// 
        ///     Critical - creates critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information) 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private static bool ExecuteCommandBinding(object sender, ExecutedRoutedEventArgs e, CommandBinding commandBinding)
        {
            // Asserting a permission in the case that the command was user initiated
            // and the command is a secure command. We can do this safely because at 
            // the time the binding was setup, we demanded the permission.
            ISecureCommand secureCommand = e.Command as ISecureCommand; 
            bool elevate = e.UserInitiated && (secureCommand != null) && (secureCommand.UserInitiatedPermission != null); 

            if (elevate) 
            {
                secureCommand.UserInitiatedPermission.Assert(); //BlessedAssert
            }
            try 
            {
                commandBinding.OnExecuted(sender, e); 
            } 
            finally
            { 
                if (elevate)
                {
                    CodeAccessPermission.RevertAssert();
                } 
            }
 
            return e.Handled; 
        }
 
        internal static void OnCommandDevice(object sender, CommandDeviceEventArgs e)
        {
            if ((sender != null) && (e != null) && (e.Command != null))
            { 
                CanExecuteRoutedEventArgs canExecuteArgs = new CanExecuteRoutedEventArgs(e.Command, null /* parameter */);
                canExecuteArgs.RoutedEvent = CommandManager.CanExecuteEvent; 
                canExecuteArgs.Source = sender; 
                OnCanExecute(sender, canExecuteArgs);
 
                if (canExecuteArgs.CanExecute)
                {
                    ExecutedRoutedEventArgs executedArgs = new ExecutedRoutedEventArgs(e.Command, null /* parameter */);
                    executedArgs.RoutedEvent = CommandManager.ExecutedEvent; 
                    executedArgs.Source = sender;
                    OnExecuted(sender, executedArgs); 
 
                    if (executedArgs.Handled)
                    { 
                        e.Handled = true;
                    }
                }
            } 
        }
 
        private static void FindCommandBinding(object sender, RoutedEventArgs e, ICommand command, bool execute) 
        {
            // Check local command bindings 
            CommandBindingCollection commandBindings = null;
            DependencyObject senderAsDO = sender as DependencyObject;
            if (InputElement.IsUIElement(senderAsDO))
            { 
                commandBindings = ((UIElement)senderAsDO).CommandBindingsInternal;
            } 
            else if (InputElement.IsContentElement(senderAsDO)) 
            {
                commandBindings = ((ContentElement)senderAsDO).CommandBindingsInternal; 
            }
            else if (InputElement.IsUIElement3D(senderAsDO))
            {
                commandBindings = ((UIElement3D)senderAsDO).CommandBindingsInternal; 
            }
            if (commandBindings != null) 
            { 
                FindCommandBinding(commandBindings, sender, e, command, execute);
            } 

            // If no command binding is found, check class command bindings
            lock (_classCommandBindings.SyncRoot)
            { 
                // Check from the current type to all the base types
                Type classType = sender.GetType(); 
                while (classType != null) 
                {
                    CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection; 
                    if (classCommandBindings != null)
                    {
                        FindCommandBinding(classCommandBindings, sender, e, command, execute);
                    } 
                    classType = classType.BaseType;
                } 
            } 
        }
 
        private static void FindCommandBinding(CommandBindingCollection commandBindings, object sender, RoutedEventArgs e, ICommand command, bool execute)
        {
            int index = 0;
            while (true) 
            {
                CommandBinding commandBinding = commandBindings.FindMatch(command, ref index); 
                if ((commandBinding == null) || 
                    (execute && ExecuteCommandBinding(sender, (ExecutedRoutedEventArgs)e, commandBinding)) ||
                    (!execute && CanExecuteCommandBinding(sender, (CanExecuteRoutedEventArgs)e, commandBinding))) 
                {
                    break;
                }
            } 
        }
 
        private static void TransferEvent(IInputElement newSource, CanExecuteRoutedEventArgs e) 
        {
            RoutedCommand command = e.Command as RoutedCommand; 
            if (command != null)
            {
                try
                { 
                    e.CanExecute = command.CanExecute(e.Parameter, newSource);
                } 
                finally 
                {
                    e.Handled = true; 
                }
            }
        }
 
        /// 
        ///     Critical - creates critical information (determining if command is driven from user input) 
        ///     TreatAsSafe - Does so correctly (only looking at protected information) 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        private static void TransferEvent(IInputElement newSource, ExecutedRoutedEventArgs e)
        {
            RoutedCommand command = e.Command as RoutedCommand;
            if (command != null) 
            {
                try 
                { 
                    // SecurityCritical: Must not modify UserInitiated
                    command.ExecuteCore(e.Parameter, newSource, e.UserInitiated); 
                }
                finally
                {
                    e.Handled = true; 
                }
            } 
        } 

        private static IInputElement GetParentScopeFocusedElement(DependencyObject childScope) 
        {
            DependencyObject parentScope = GetParentScope(childScope);
            if (parentScope != null)
            { 
                IInputElement focusedElement = FocusManager.GetFocusedElement(parentScope);
                if ((focusedElement != null) && !ContainsElement(childScope, focusedElement as DependencyObject)) 
                { 
                    // The focused element from the parent focus scope is not within the focus scope
                    // of the current element. 
                    return focusedElement;
                }
            }
 
            return null;
        } 
 
        private static DependencyObject GetParentScope(DependencyObject childScope)
        { 
            // Get the parent element of the childScope element
            DependencyObject parent = null;
            UIElement element = childScope as UIElement;
            ContentElement contentElement = (element == null) ? childScope as ContentElement : null; 
            UIElement3D element3D = (element == null && contentElement == null) ? childScope as UIElement3D : null;
 
            if (element != null) 
            {
                parent = element.GetUIParent(true); 
            }
            else if (contentElement != null)
            {
                parent = contentElement.GetUIParent(true); 
            }
            else if (element3D != null) 
            { 
                parent = element3D.GetUIParent(true);
            } 

            if (parent != null)
            {
                // Get the next focus scope above this one 
                return FocusManager.GetFocusScope(parent);
            } 
 
            return null;
        } 

        private static bool ContainsElement(DependencyObject scope, DependencyObject child)
        {
            if (child != null) 
            {
                DependencyObject parentScope = FocusManager.GetFocusScope(child); 
                while (parentScope != null) 
                {
                    if (parentScope == scope) 
                    {
                        // A parent scope matches the scope we are looking for
                        return true;
                    } 
                    parentScope = GetParentScope(parentScope);
                } 
            } 

            return false; 
        }

        #endregion
 
        #region Data
 
        // The CommandManager associated with the current thread 
        [ThreadStatic]
        private static CommandManager _commandManager; 

        // This is a Hashtable of CommandBindingCollections keyed on OwnerType
        // Each ItemList holds the registered Class level CommandBindings for that OwnerType
        private static HybridDictionary _classCommandBindings = new HybridDictionary(); 

        // This is a Hashtable of InputBindingCollections keyed on OwnerType 
        // Each Item holds the registered Class level CommandBindings for that OwnerType 
        private static HybridDictionary _classInputBindings = new HybridDictionary();
 
        #endregion

        #endregion
 
        #region Instance Features
 
        #region Constructor 

        /// 
        ///     Creates a new instance of this class.
        ///
        private CommandManager()
        { 
        }
 
        #endregion 

        #region Implementation 

        /// 
        ///     Adds an idle priority dispatcher operation to raise RequerySuggested.
        ///  
        private void RaiseRequerySuggested()
        { 
            if (_requerySuggestedOperation == null) 
            {
                Dispatcher dispatcher = Dispatcher.CurrentDispatcher; 
                if ((dispatcher != null) && !dispatcher.HasShutdownStarted && !dispatcher.HasShutdownFinished)
                {
                    _requerySuggestedOperation = dispatcher.BeginInvoke(DispatcherPriority.Background, new DispatcherOperationCallback(RaiseRequerySuggested), null);
                } 
            }
        } 
 
        private object RaiseRequerySuggested(object obj)
        { 
            // Call the RequerySuggested handlers
            _requerySuggestedOperation = null;
            CommandManager.CallWeakReferenceHandlers(_requerySuggestedHandlers);
            return null; 
        }
 
        internal static void CallWeakReferenceHandlers(List handlers) 
        {
            if (handlers != null) 
            {
                // Take a snapshot of the handlers before we call out to them since the handlers
                // could cause the array to me modified while we are reading it.
 
                EventHandler[] callees = new EventHandler[handlers.Count];
                int count = 0; 
 
                for (int i = handlers.Count - 1; i >= 0; i--)
                { 
                    WeakReference reference = handlers[i];
                    EventHandler handler = reference.Target as EventHandler;
                    if (handler == null)
                    { 
                        // Clean up old handlers that have been collected
                        handlers.RemoveAt(i); 
                    } 
                    else
                    { 
                        callees[count] = handler;
                        count++;
                    }
                } 

                // Call the handlers that we snapshotted 
                for (int i = 0; i < count; i++) 
                {
                    EventHandler handler = callees[i]; 
                    handler(null, EventArgs.Empty);
                }
            }
        } 

        internal static void AddWeakReferenceHandler(ref List handlers, EventHandler handler) 
        { 
            if (handlers == null)
            { 
                handlers = new List();
            }

            handlers.Add(new WeakReference(handler)); 
        }
 
        internal static void RemoveWeakReferenceHandler(List handlers, EventHandler handler) 
        {
            if (handlers != null) 
            {
                for (int i = handlers.Count - 1; i >= 0; i--)
                {
                    WeakReference reference = handlers[i]; 
                    EventHandler existingHandler = reference.Target as EventHandler;
                    if ((existingHandler == null) || (existingHandler == handler)) 
                    { 
                        // Clean up old handlers that have been collected
                        // in addition to the handler that is to be removed. 
                        handlers.RemoveAt(i);
                    }
                }
            } 
        }
 
        #endregion 

        #region Data 

        // This is the event we fire when told to InvalidateStatus
        private List _requerySuggestedHandlers;
 
        // An operation object indicating that a callback is already on the dispatcher
        private DispatcherOperation _requerySuggestedOperation = null; 
 
        #endregion
 
        #endregion
    }
}

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