Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / EventRoute.cs / 2 / EventRoute.cs
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using MS.Utility; using SR=MS.Internal.PresentationCore.SR; using SRID=MS.Internal.PresentationCore.SRID; using MS.Internal; namespace System.Windows { ////// Container for the route to be followed /// by a RoutedEvent when raised /// ////// EventRoute constitues public sealed class EventRoute { #region Construction ////// a non-null /// and /// an ordered list of (target object, handler list) /// pairs /// /// /// It facilitates adding new entries to this list /// and also allows for the handlers in the list /// to be invoked /// /// Constructor for /// /// Non-nullgiven /// the associated /// to be associated with /// this /// public EventRoute(RoutedEvent routedEvent) { if (routedEvent == null) { throw new ArgumentNullException("routedEvent"); } _routedEvent = routedEvent; // Changed the initialization size to 16 // to achieve performance gain based // on standard app behavior _routeItemList = new FrugalStructList (16); _sourceItemList = new FrugalStructList (16); } #endregion Construction #region External API /// /// Adds this handler for the /// specified target to the route /// ////// NOTE: It is not an error to add a /// handler for a particular target instance /// twice (handler will simply be called twice). /// /// /// Target object whose handler is to be /// added to the route /// /// /// Handler to be added to the route /// /// /// Flag indicating whether or not the listener wants to /// hear about events that have already been handled /// public void Add(object target, Delegate handler, bool handledEventsToo) { if (target == null) { throw new ArgumentNullException("target"); } if (handler == null) { throw new ArgumentNullException("handler"); } RouteItem routeItem = new RouteItem(target, new RoutedEventHandlerInfo(handler, handledEventsToo)); _routeItemList.Add(routeItem); } ////// Invokes all the handlers that have been /// added to the route /// ////// NOTE: If the /// ////// of the associated /// is /// the last handlers added are the /// last ones invoked /// However if the /// of the associated /// is , /// the last handlers added are the /// first ones invoked /// /// that raised the RoutedEvent /// /// /// that carry /// all the details specific to this RoutedEvent /// internal void InvokeHandlers(object source, RoutedEventArgs args) { InvokeHandlersImpl(source, args, false); } internal void ReInvokeHandlers(object source, RoutedEventArgs args) { InvokeHandlersImpl(source, args, true); } private void InvokeHandlersImpl(object source, RoutedEventArgs args, bool reRaised) { if (source == null) { throw new ArgumentNullException("source"); } if (args == null) { throw new ArgumentNullException("args"); } if (args.Source == null) { throw new ArgumentException(SR.Get(SRID.SourceNotSet)); } if (args.RoutedEvent != _routedEvent) { throw new ArgumentException(SR.Get(SRID.Mismatched_RoutedEvent)); } // Check RoutingStrategy to know the order of invocation if (args.RoutedEvent.RoutingStrategy == RoutingStrategy.Bubble || args.RoutedEvent.RoutingStrategy == RoutingStrategy.Direct) { int endSourceChangeIndex = 0; // If the RoutingStrategy of the associated is // Bubble the handlers for the last target // added are the last ones invoked // Invoke class listeners for (int i=0; i<_routeItemList.Count; i++) { // Query for new source only if we are // past the range of the previous source change if (i >= endSourceChangeIndex) { // Get the source at this point in the bubble route and also // the index at which this source change seizes to apply object newSource = GetBubbleSource(i, out endSourceChangeIndex); // Set appropriate source // The first call to setsource seems redundant // but is necessary because the source could have // been modified during BuildRoute call and hence // may need to be reset to the original source. // Note: we skip this logic if reRaised is set, which is done when we're trying // to convert MouseDown/Up into a MouseLeft/RightButtonDown/Up if(!reRaised) { if (newSource == null) args.Source=source; else args.Source=newSource; } } // Invoke listeners if( TraceRoutedEvent.IsEnabled ) { TraceRoutedEvent.Trace( TraceEventType.Start, TraceRoutedEvent.InvokeHandlers, _routeItemList[i].Target, args, args.Handled ); } _routeItemList[i].InvokeHandler(args); if( TraceRoutedEvent.IsEnabled ) { TraceRoutedEvent.Trace( TraceEventType.Stop, TraceRoutedEvent.InvokeHandlers, _routeItemList[i].Target, args, args.Handled ); } } } else { int startSourceChangeIndex = _routeItemList.Count; int endTargetIndex =_routeItemList.Count-1; int startTargetIndex; // If the RoutingStrategy of the associated is // Tunnel the handlers for the last target // added are the first ones invoked while (endTargetIndex >= 0) { // For tunnel events we need to invoke handlers for the last target first. // However the handlers for that individual target must be fired in the right order. // Eg. Class Handlers must be fired before Instance Handlers. object currTarget = _routeItemList[endTargetIndex].Target; for (startTargetIndex=endTargetIndex; startTargetIndex>=0; startTargetIndex--) { if (_routeItemList[startTargetIndex].Target != currTarget) { break; } } for (int i=startTargetIndex+1; i<=endTargetIndex; i++) { // Query for new source only if we are // past the range of the previous source change if (i < startSourceChangeIndex) { // Get the source at this point in the tunnel route and also // the index at which this source change seizes to apply object newSource = GetTunnelSource(i, out startSourceChangeIndex); // Set appropriate source // The first call to setsource seems redundant // but is necessary because the source could have // been modified during BuildRoute call and hence // may need to be reset to the original source. if (newSource == null) args.Source=source; else args.Source=newSource; } if( TraceRoutedEvent.IsEnabled ) { TraceRoutedEvent.Trace( TraceEventType.Start, TraceRoutedEvent.InvokeHandlers, _routeItemList[i].Target, args, args.Handled ); } // Invoke listeners _routeItemList[i].InvokeHandler(args); if( TraceRoutedEvent.IsEnabled ) { TraceRoutedEvent.Trace( TraceEventType.Stop, TraceRoutedEvent.InvokeHandlers, _routeItemList[i].Target, args, args.Handled ); } } endTargetIndex = startTargetIndex; } } } /// /// Pushes the given node at the top of the stack of branches. /// ////// If a node in the tree has different visual and logical, /// FrameworkElement will store the node on this stack of /// branches. If the route ever returns to the same logical /// tree, the event source will be restored. /// /// /// The node where the visual parent is different from the logical /// parent. /// /// /// The source that is currently being used, and which should be /// restored when this branch is popped off the stack. /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] public void PushBranchNode(object node, object source) { BranchNode branchNode = new BranchNode(); branchNode.Node = node; branchNode.Source = source; BranchNodeStack.Push(branchNode); } ////// NOTE: This method needs to be public because it is used /// by FrameworkElement. /// /// Pops the given node from the top of the stack of branches. /// ////// If a node in the tree has different visual and logical, /// FrameworkElement will store the node on this stack of /// branches. If the route ever returns to the same logical /// tree, the event source will be restored. /// ////// NOTE: This method needs to be public because it is used /// by FrameworkElement. /// /// The node where the visual parent was different from the /// logical parent. /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] public object PopBranchNode() { if (BranchNodeStack.Count == 0) return null; BranchNode branchNode = BranchNodeStack.Pop(); return branchNode.Node; } ////// Peeks the given node from the top of the stack of branches. /// ////// If a node in the tree has different visual and logical, /// FrameworkElement will store the node on this stack of /// branches. If the route ever returns to the same logical /// tree, the event source will be restored. /// ////// NOTE: This method needs to be public because it is used /// by FrameworkElement. /// /// The node where the visual parent was different from the /// logical parent. /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] public object PeekBranchNode() { if (BranchNodeStack.Count == 0) return null; BranchNode branchNode = BranchNodeStack.Peek(); return branchNode.Node; } ////// Peeks the given source from the top of the stack of branches. /// ////// If a node in the tree has different visual and logical, /// FrameworkElement will store the node on this stack of /// branches. If the route ever returns to the same logical /// tree, the event source will be restored. /// ////// NOTE: This method needs to be public because it is used /// by FrameworkElement. /// /// The source that was stored along with the node where the /// visual parent was different from the logical parent. /// [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Advanced)] public object PeekBranchSource() { if (BranchNodeStack.Count == 0) return null; BranchNode branchNode = BranchNodeStack.Peek(); return branchNode.Source; } #endregion External API #region Operations // Return associated RoutedEvent internal RoutedEvent RoutedEvent { get {return _routedEvent;} set { _routedEvent = value; } } // A BranchNode indicates a point in the tree where the logical and // visual structure might diverge. When building a route, we store // this branch node for every logical link we find. Along with the // node where the possible divergence occurred, we store the source // that the event should use. This is so that the source of an // event will always be in the logical tree of the element handling // the event. private struct BranchNode { public object Node; public object Source; } // Branch nodes are stored on a stack, which we create on-demand. private StackBranchNodeStack { get { if (_branchNodeStack == null) { _branchNodeStack = new Stack (1); } return _branchNodeStack; } } // Add the given source to the source item list // indicating what the source will be this point // onwards in the route internal void AddSource(object source) { int startIndex = _routeItemList.Count; _sourceItemList.Add(new SourceItem(startIndex, source)); } // Determine what the RoutedEventArgs.Source should be, at this // point in the bubble. Also the endIndex output parameter tells // you the exact index of the handlersList at which this source // change ceases to apply private object GetBubbleSource(int index, out int endIndex) { // If the Source never changes during the route execution, // then we're done (just return null). if (_sourceItemList.Count == 0) { endIndex = _routeItemList.Count; return null; } // Similarly, if we're not to the point of the route of the first Source // change, simply return null. if (index < _sourceItemList[0].StartIndex) { endIndex = _sourceItemList[0].StartIndex; return null; } // See if we should be using one of the intermediate // sources for (int i=0; i<_sourceItemList.Count -1; i++) { if (index >= _sourceItemList[i].StartIndex && index < _sourceItemList[i+1].StartIndex) { endIndex = _sourceItemList[i+1].StartIndex; return _sourceItemList[i].Source; } } // If we get here, we're on the last one, // so return that. endIndex = _routeItemList.Count; return _sourceItemList[_sourceItemList.Count -1].Source; } // Determine what the RoutedEventArgs.Source should be, at this // point in the tunnel. Also the startIndex output parameter tells // you the exact index of the handlersList at which this source // change starts to apply private object GetTunnelSource(int index, out int startIndex) { // If the Source never changes during the route execution, // then we're done (just return null). if (_sourceItemList.Count == 0) { startIndex = 0; return null; } // Similarly, if we're past the point of the route of the first Source // change, simply return null. if (index < _sourceItemList[0].StartIndex) { startIndex = 0; return null; } // See if we should be using one of the intermediate // sources for (int i=0; i<_sourceItemList.Count -1; i++) { if (index >= _sourceItemList[i].StartIndex && index < _sourceItemList[i+1].StartIndex) { startIndex = _sourceItemList[i].StartIndex; return _sourceItemList[i].Source; } } // If we get here, we're on the last one, so return that. startIndex = _sourceItemList[_sourceItemList.Count -1].StartIndex; return _sourceItemList[_sourceItemList.Count -1].Source; } /// /// Cleanup all the references within the data /// internal void Clear() { _routedEvent = null; _routeItemList.Clear(); if (_branchNodeStack != null) { _branchNodeStack.Clear(); } _sourceItemList.Clear(); } #endregion Operations #region Data private RoutedEvent _routedEvent; // Stores the routed event handlers to be // invoked for the associated RoutedEvent private FrugalStructList_routeItemList; // Stores the branching nodes in the route // that need to be backtracked while // augmenting the route private Stack _branchNodeStack; // Stores Source Items for separated trees private FrugalStructList _sourceItemList; #endregion Data } } // 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
- DesignerEditorPartChrome.cs
- ImageListUtils.cs
- StringAnimationBase.cs
- MenuItemBinding.cs
- ClipboardProcessor.cs
- XmlSchemaSet.cs
- _ShellExpression.cs
- TextParagraphCache.cs
- XmlSchemaAttribute.cs
- KeyedByTypeCollection.cs
- Compress.cs
- TextBounds.cs
- SyndicationSerializer.cs
- TreeNodeStyleCollectionEditor.cs
- RtfFormatStack.cs
- SafeTimerHandle.cs
- KeyTime.cs
- StreamHelper.cs
- IPHostEntry.cs
- DataSourceSelectArguments.cs
- COSERVERINFO.cs
- Deflater.cs
- XmlDesigner.cs
- exports.cs
- ResXResourceSet.cs
- CompareValidator.cs
- PartialArray.cs
- SimpleApplicationHost.cs
- TextDecoration.cs
- DesignerActionService.cs
- FormViewCommandEventArgs.cs
- WindowsListViewScroll.cs
- ComplexTypeEmitter.cs
- WebRequestModuleElementCollection.cs
- SiteMapNodeCollection.cs
- _RequestCacheProtocol.cs
- ConfigurationValidatorAttribute.cs
- GlobalEventManager.cs
- ObjectViewEntityCollectionData.cs
- TextFindEngine.cs
- FacetValueContainer.cs
- ZipIOExtraField.cs
- RuntimeConfigLKG.cs
- FrameworkReadOnlyPropertyMetadata.cs
- InputMethod.cs
- Size.cs
- CodeTypeReferenceExpression.cs
- WebPartConnectionsCloseVerb.cs
- SocketElement.cs
- XpsFixedDocumentSequenceReaderWriter.cs
- AutomationIdentifierGuids.cs
- ListViewInsertionMark.cs
- DiffuseMaterial.cs
- Model3D.cs
- InnerItemCollectionView.cs
- BitmapFrameEncode.cs
- x509store.cs
- SchemaNames.cs
- MenuEventArgs.cs
- PerfCounters.cs
- SendActivityEventArgs.cs
- PseudoWebRequest.cs
- XmlWellformedWriter.cs
- AsymmetricAlgorithm.cs
- TransferMode.cs
- ContextDataSource.cs
- EncodingNLS.cs
- RawStylusInputCustomData.cs
- SqlClientWrapperSmiStream.cs
- StylusButtonEventArgs.cs
- ListViewDeletedEventArgs.cs
- Asn1Utilities.cs
- KnownBoxes.cs
- SiteIdentityPermission.cs
- Attachment.cs
- RangeContentEnumerator.cs
- XmlTypeAttribute.cs
- ProofTokenCryptoHandle.cs
- IssuanceTokenProviderBase.cs
- CallTemplateAction.cs
- EntityModelBuildProvider.cs
- PenContexts.cs
- DetailsViewUpdateEventArgs.cs
- WindowsListViewItemCheckBox.cs
- RoutedEventHandlerInfo.cs
- SpellerHighlightLayer.cs
- Vector3DAnimationUsingKeyFrames.cs
- SplitterCancelEvent.cs
- SkipStoryboardToFill.cs
- FactoryMaker.cs
- GridViewPageEventArgs.cs
- EventPrivateKey.cs
- HttpGetProtocolReflector.cs
- Operators.cs
- HttpInputStream.cs
- PackagingUtilities.cs
- SmtpClient.cs
- SaveFileDialogDesigner.cs
- MarkupCompiler.cs
- MethodRental.cs