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
- CommandManager.cs
- ConstraintConverter.cs
- DataGridSortCommandEventArgs.cs
- ConfigurationSectionGroup.cs
- CompensatableTransactionScopeActivity.cs
- ScriptManager.cs
- DataGridViewColumn.cs
- BrowserCapabilitiesFactoryBase.cs
- XamlBrushSerializer.cs
- UserControl.cs
- ScrollBar.cs
- WMIGenerator.cs
- ParamArrayAttribute.cs
- DateTimeSerializationSection.cs
- X509SubjectKeyIdentifierClause.cs
- SystemBrushes.cs
- UnsettableComboBox.cs
- MimeWriter.cs
- HttpListenerException.cs
- Encoder.cs
- RichTextBoxConstants.cs
- TextTreeRootNode.cs
- EntityContainerRelationshipSetEnd.cs
- CounterSampleCalculator.cs
- TypedDataSetSchemaImporterExtensionFx35.cs
- DefaultPropertyAttribute.cs
- CultureInfo.cs
- _AcceptOverlappedAsyncResult.cs
- HeaderPanel.cs
- Span.cs
- RecordConverter.cs
- StylusPlugin.cs
- DateTimeAutomationPeer.cs
- TextTreeTextElementNode.cs
- CachingHintValidation.cs
- DependencyPropertyConverter.cs
- BindingsSection.cs
- ObjectView.cs
- SqlProvider.cs
- HandlerFactoryCache.cs
- Action.cs
- DesignTimeResourceProviderFactoryAttribute.cs
- WebPartDisplayModeCollection.cs
- PageCatalogPart.cs
- SatelliteContractVersionAttribute.cs
- InputReport.cs
- ContentType.cs
- RSAPKCS1SignatureDeformatter.cs
- Events.cs
- OLEDB_Enum.cs
- HiddenFieldPageStatePersister.cs
- ReplacementText.cs
- ResourceDisplayNameAttribute.cs
- ImageKeyConverter.cs
- WindowsScrollBarBits.cs
- DataSourceView.cs
- Paragraph.cs
- MenuItemStyle.cs
- Ipv6Element.cs
- EntityProxyTypeInfo.cs
- PersonalizationProviderCollection.cs
- documentsequencetextpointer.cs
- ISO2022Encoding.cs
- Privilege.cs
- Int16AnimationUsingKeyFrames.cs
- DefaultTextStoreTextComposition.cs
- X509Utils.cs
- EasingKeyFrames.cs
- ApplicationDirectoryMembershipCondition.cs
- ITreeGenerator.cs
- safesecurityhelperavalon.cs
- TimeIntervalCollection.cs
- QueryableFilterRepeater.cs
- MimeParameter.cs
- VariableBinder.cs
- TranslateTransform.cs
- EdmProviderManifest.cs
- AncillaryOps.cs
- CodeRemoveEventStatement.cs
- CodeGroup.cs
- Cell.cs
- SetIterators.cs
- UIPermission.cs
- FileVersion.cs
- SchemaEntity.cs
- LinqDataSourceStatusEventArgs.cs
- ConfigurationManagerHelperFactory.cs
- WebRequestModuleElement.cs
- SortedList.cs
- CompiledELinqQueryState.cs
- ClaimTypes.cs
- StrongNameUtility.cs
- ZipPackage.cs
- DisplayMemberTemplateSelector.cs
- httpapplicationstate.cs
- PageSettings.cs
- FormParameter.cs
- PasswordRecovery.cs
- RecordBuilder.cs
- FixedSOMLineCollection.cs