Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / wpf / src / Framework / System / Windows / EventTrigger.cs / 1 / EventTrigger.cs
/****************************************************************************\ * * File: EventTrigger.cs * * An event trigger is a set of actions that will be activated in response to * the specified event fired elsewhere. * * Copyright (C) by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System.Collections; using System.Diagnostics; using System.Windows.Markup; using System.Collections.Specialized; using System.ComponentModel; namespace System.Windows { ////// A class that controls a set of actions to activate in response to an event /// [ContentProperty("Actions")] public class EventTrigger : TriggerBase, IAddChild { /////////////////////////////////////////////////////////////////////// // Public members ////// Build an empty instance of the EventTrigger object /// public EventTrigger() { } ////// Build an instance of EventTrigger associated with the given event /// public EventTrigger( RoutedEvent routedEvent ) { RoutedEvent = routedEvent; } ////// Add an object child to this trigger's Actions /// void IAddChild.AddChild(object value) { AddChild(value); } ////// Add an object child to this trigger's Actions /// protected virtual void AddChild(object value) { TriggerAction action = value as TriggerAction; if (action == null) { throw new ArgumentException(SR.Get(SRID.EventTriggerBadAction, value.GetType().Name)); } Actions.Add(action); } ////// Add a text string to this trigger's Actions. Note that this /// is not supported and will result in an exception. /// void IAddChild.AddText(string text) { AddText(text); } ////// Add a text string to this trigger's Actions. Note that this /// is not supported and will result in an exception. /// protected virtual void AddText(string text) { XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); } ////// The Event that will activate this trigger - one must be specified /// before an event trigger is meaningful. /// public RoutedEvent RoutedEvent { get { return _routedEvent; } set { if ( value == null ) { throw new ArgumentNullException("value"); } if( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } // When used as an element trigger, we don't actually need to seal // to ensure cross-thread usability. However, if we *are* fixed on // listening to an event already, don't allow this change. if( _routedEventHandler != null ) { // Recycle the Seal error message. throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } _routedEvent = value; } } ////// The x:Name of the object whose event shall trigger this /// EventTrigger. If null, then this is the object being Styled /// and not anything under its Style.VisualTree. /// [DefaultValue(null)] public string SourceName { get { return _sourceName; } set { if( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } _sourceName = value; } } ////// Internal method to get the childId corresponding to the public /// sourceId. /// internal int TriggerChildIndex { get { return _childId; } set { _childId = value; } } ////// The collection of actions to activate when the Event occurs. /// At least one action is required for the trigger to be meaningful. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public TriggerActionCollection Actions { get { if( _actions == null ) { _actions = new TriggerActionCollection(); // Give the collection a back-link, this is used for the inheritance context _actions.Owner = this; } return _actions; } } ////// If we get a new inheritance context (or it goes to null) /// we need to tell actions about it. /// internal override void OnInheritanceContextChangedCore(EventArgs args) { base.OnInheritanceContextChangedCore(args); if (_actions == null) { return; } for (int i=0; i<_actions.Count; i++) { DependencyObject action = _actions[i] as DependencyObject; if (action != null && action.InheritanceContext == this) { action.OnInheritanceContextChanged(args); } } } ////// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeActions() { return ( _actions != null && _actions.Count > 0 ); } /////////////////////////////////////////////////////////////////////// // Internal members internal sealed override void Seal() { if( PropertyValues.Count > 0 ) { throw new InvalidOperationException(SR.Get(SRID.EventTriggerDoNotSetProperties)); } // EnterActions/ExitActions aren't meaningful on event triggers. if( HasEnterActions || HasExitActions ) { throw new InvalidOperationException(SR.Get(SRID.EventTriggerDoesNotEnterExit)); } if (_routedEvent != null && _actions != null && _actions.Count > 0) { _actions.Seal(this); // TriggerActions need a link back to me to fetch the childId corresponding the sourceId string. } base.Seal(); // Should be almost a no-op given lack of PropertyValues } /////////////////////////////////////////////////////////////////////// // Private members // Event that will fire this trigger private RoutedEvent _routedEvent = null; // Name of the Style.VisualTree node whose event to listen to. // May remain the default value of null, which means the object being // Styled is the target instead of something within the Style.VisualTree. private string _sourceName = null; // Style childId corresponding to the SourceName string private int _childId = 0; // Actions to invoke when this trigger is fired private TriggerActionCollection _actions = null; /////////////////////////////////////////////////////////////////////// // Storage attached to other objects to support triggers // Some of these can be moved to base class as necessary. // Exists on objects that have information in their [Class].Triggers collection property. (Currently root FrameworkElement only.) internal static readonly UncommonFieldTriggerCollectionField = new UncommonField (null); // This is the listener that we hook up to the SourceId element. RoutedEventHandler _routedEventHandler = null; // This is the SourceId-ed element. FrameworkElement _source; /////////////////////////////////////////////////////////////////////// // Internal static methods to process event trigger information stored // in attached storage of other objects. // // Called when the FrameworkElement and the tree structure underneath it has been // built up. This is the earliest point we can resolve all the child // node identification that may exist in a Trigger object. // This should be moved to base class if PropertyTrigger support is added. internal static void ProcessTriggerCollection( FrameworkElement triggersHost ) { TriggerCollection triggerCollection = TriggerCollectionField.GetValue(triggersHost); if( triggerCollection != null ) { // Don't seal the collection, because we allow it to change. We will, // however, seal each of the triggers. for( int i = 0; i < triggerCollection.Count; i++ ) { ProcessOneTrigger( triggersHost, triggerCollection[i] ); } } } //////////////////////////////////////////////////////////////////////// // ProcessOneTrigger // // Find the target element for this trigger, and set a listener for // the event into (pointing back to the trigger). internal static void ProcessOneTrigger( FrameworkElement triggersHost, TriggerBase triggerBase ) { // This code path is used in the element trigger case. We don't actually // need these guys to be usable cross-thread, so we don't really need // to freeze/seal these objects. The only one expected to cause problems // is a change to the RoutedEvent. At the same time we remove this // Seal(), the RoutedEvent setter will check to see if the handler has // already been created and refuse an update if so. // triggerBase.Seal(); EventTrigger eventTrigger = triggerBase as EventTrigger; if( eventTrigger != null ) { Debug.Assert( eventTrigger._routedEventHandler == null && eventTrigger._source == null); // PERF: Cache this result if it turns out we're doing a lot of lookups on the same name. eventTrigger._source = FrameworkElement.FindNamedFrameworkElement( triggersHost, eventTrigger.SourceName ); // Create a statefull event delegate (which keeps a ref to the FE). EventTriggerSourceListener listener = new EventTriggerSourceListener( eventTrigger, triggersHost ); // Store the RoutedEventHandler & target for use in DisconnectOneTrigger eventTrigger._routedEventHandler = new RoutedEventHandler(listener.Handler); eventTrigger._source.AddHandler( eventTrigger.RoutedEvent, eventTrigger._routedEventHandler, false /* HandledEventsToo */ ); } else { throw new InvalidOperationException(SR.Get(SRID.TriggersSupportsEventTriggersOnly)); } } //////////////////////////////////////////////////////////////////////// // // DisconnectAllTriggers // // Call DisconnectOneTrigger for each trigger in the Triggers collection. internal static void DisconnectAllTriggers( FrameworkElement triggersHost ) { TriggerCollection triggerCollection = TriggerCollectionField.GetValue(triggersHost); if( triggerCollection != null ) { for( int i = 0; i < triggerCollection.Count; i++ ) { DisconnectOneTrigger( triggersHost, triggerCollection[i] ); } } } //////////////////////////////////////////////////////////////////////// // // DisconnectOneTrigger // // In ProcessOneTrigger, we connect an event trigger to the element // which it targets. Here, we remove the event listener to clean up. internal static void DisconnectOneTrigger( FrameworkElement triggersHost, TriggerBase triggerBase ) { EventTrigger eventTrigger = triggerBase as EventTrigger; if( eventTrigger != null ) { eventTrigger._source.RemoveHandler( eventTrigger.RoutedEvent, eventTrigger._routedEventHandler); eventTrigger._routedEventHandler = null; } else { throw new InvalidOperationException(SR.Get(SRID.TriggersSupportsEventTriggersOnly)); } } internal class EventTriggerSourceListener { internal EventTriggerSourceListener( EventTrigger trigger, FrameworkElement host ) { _owningTrigger = trigger; _owningTriggerHost = host; } internal void Handler(object sender, RoutedEventArgs e) { // Invoke all actions of the associated EventTrigger object. TriggerActionCollection actions = _owningTrigger.Actions; for( int j = 0; j < actions.Count; j++ ) { actions[j].Invoke(_owningTriggerHost); } } private EventTrigger _owningTrigger; private FrameworkElement _owningTriggerHost; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. /****************************************************************************\ * * File: EventTrigger.cs * * An event trigger is a set of actions that will be activated in response to * the specified event fired elsewhere. * * Copyright (C) by Microsoft Corporation. All rights reserved. * \***************************************************************************/ using System.Collections; using System.Diagnostics; using System.Windows.Markup; using System.Collections.Specialized; using System.ComponentModel; namespace System.Windows { /// /// A class that controls a set of actions to activate in response to an event /// [ContentProperty("Actions")] public class EventTrigger : TriggerBase, IAddChild { /////////////////////////////////////////////////////////////////////// // Public members ////// Build an empty instance of the EventTrigger object /// public EventTrigger() { } ////// Build an instance of EventTrigger associated with the given event /// public EventTrigger( RoutedEvent routedEvent ) { RoutedEvent = routedEvent; } ////// Add an object child to this trigger's Actions /// void IAddChild.AddChild(object value) { AddChild(value); } ////// Add an object child to this trigger's Actions /// protected virtual void AddChild(object value) { TriggerAction action = value as TriggerAction; if (action == null) { throw new ArgumentException(SR.Get(SRID.EventTriggerBadAction, value.GetType().Name)); } Actions.Add(action); } ////// Add a text string to this trigger's Actions. Note that this /// is not supported and will result in an exception. /// void IAddChild.AddText(string text) { AddText(text); } ////// Add a text string to this trigger's Actions. Note that this /// is not supported and will result in an exception. /// protected virtual void AddText(string text) { XamlSerializerUtil.ThrowIfNonWhiteSpaceInAddText(text, this); } ////// The Event that will activate this trigger - one must be specified /// before an event trigger is meaningful. /// public RoutedEvent RoutedEvent { get { return _routedEvent; } set { if ( value == null ) { throw new ArgumentNullException("value"); } if( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } // When used as an element trigger, we don't actually need to seal // to ensure cross-thread usability. However, if we *are* fixed on // listening to an event already, don't allow this change. if( _routedEventHandler != null ) { // Recycle the Seal error message. throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } _routedEvent = value; } } ////// The x:Name of the object whose event shall trigger this /// EventTrigger. If null, then this is the object being Styled /// and not anything under its Style.VisualTree. /// [DefaultValue(null)] public string SourceName { get { return _sourceName; } set { if( IsSealed ) { throw new InvalidOperationException(SR.Get(SRID.CannotChangeAfterSealed, "EventTrigger")); } _sourceName = value; } } ////// Internal method to get the childId corresponding to the public /// sourceId. /// internal int TriggerChildIndex { get { return _childId; } set { _childId = value; } } ////// The collection of actions to activate when the Event occurs. /// At least one action is required for the trigger to be meaningful. /// [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public TriggerActionCollection Actions { get { if( _actions == null ) { _actions = new TriggerActionCollection(); // Give the collection a back-link, this is used for the inheritance context _actions.Owner = this; } return _actions; } } ////// If we get a new inheritance context (or it goes to null) /// we need to tell actions about it. /// internal override void OnInheritanceContextChangedCore(EventArgs args) { base.OnInheritanceContextChangedCore(args); if (_actions == null) { return; } for (int i=0; i<_actions.Count; i++) { DependencyObject action = _actions[i] as DependencyObject; if (action != null && action.InheritanceContext == this) { action.OnInheritanceContextChanged(args); } } } ////// This method is used by TypeDescriptor to determine if this property should /// be serialized. /// [EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeActions() { return ( _actions != null && _actions.Count > 0 ); } /////////////////////////////////////////////////////////////////////// // Internal members internal sealed override void Seal() { if( PropertyValues.Count > 0 ) { throw new InvalidOperationException(SR.Get(SRID.EventTriggerDoNotSetProperties)); } // EnterActions/ExitActions aren't meaningful on event triggers. if( HasEnterActions || HasExitActions ) { throw new InvalidOperationException(SR.Get(SRID.EventTriggerDoesNotEnterExit)); } if (_routedEvent != null && _actions != null && _actions.Count > 0) { _actions.Seal(this); // TriggerActions need a link back to me to fetch the childId corresponding the sourceId string. } base.Seal(); // Should be almost a no-op given lack of PropertyValues } /////////////////////////////////////////////////////////////////////// // Private members // Event that will fire this trigger private RoutedEvent _routedEvent = null; // Name of the Style.VisualTree node whose event to listen to. // May remain the default value of null, which means the object being // Styled is the target instead of something within the Style.VisualTree. private string _sourceName = null; // Style childId corresponding to the SourceName string private int _childId = 0; // Actions to invoke when this trigger is fired private TriggerActionCollection _actions = null; /////////////////////////////////////////////////////////////////////// // Storage attached to other objects to support triggers // Some of these can be moved to base class as necessary. // Exists on objects that have information in their [Class].Triggers collection property. (Currently root FrameworkElement only.) internal static readonly UncommonFieldTriggerCollectionField = new UncommonField (null); // This is the listener that we hook up to the SourceId element. RoutedEventHandler _routedEventHandler = null; // This is the SourceId-ed element. FrameworkElement _source; /////////////////////////////////////////////////////////////////////// // Internal static methods to process event trigger information stored // in attached storage of other objects. // // Called when the FrameworkElement and the tree structure underneath it has been // built up. This is the earliest point we can resolve all the child // node identification that may exist in a Trigger object. // This should be moved to base class if PropertyTrigger support is added. internal static void ProcessTriggerCollection( FrameworkElement triggersHost ) { TriggerCollection triggerCollection = TriggerCollectionField.GetValue(triggersHost); if( triggerCollection != null ) { // Don't seal the collection, because we allow it to change. We will, // however, seal each of the triggers. for( int i = 0; i < triggerCollection.Count; i++ ) { ProcessOneTrigger( triggersHost, triggerCollection[i] ); } } } //////////////////////////////////////////////////////////////////////// // ProcessOneTrigger // // Find the target element for this trigger, and set a listener for // the event into (pointing back to the trigger). internal static void ProcessOneTrigger( FrameworkElement triggersHost, TriggerBase triggerBase ) { // This code path is used in the element trigger case. We don't actually // need these guys to be usable cross-thread, so we don't really need // to freeze/seal these objects. The only one expected to cause problems // is a change to the RoutedEvent. At the same time we remove this // Seal(), the RoutedEvent setter will check to see if the handler has // already been created and refuse an update if so. // triggerBase.Seal(); EventTrigger eventTrigger = triggerBase as EventTrigger; if( eventTrigger != null ) { Debug.Assert( eventTrigger._routedEventHandler == null && eventTrigger._source == null); // PERF: Cache this result if it turns out we're doing a lot of lookups on the same name. eventTrigger._source = FrameworkElement.FindNamedFrameworkElement( triggersHost, eventTrigger.SourceName ); // Create a statefull event delegate (which keeps a ref to the FE). EventTriggerSourceListener listener = new EventTriggerSourceListener( eventTrigger, triggersHost ); // Store the RoutedEventHandler & target for use in DisconnectOneTrigger eventTrigger._routedEventHandler = new RoutedEventHandler(listener.Handler); eventTrigger._source.AddHandler( eventTrigger.RoutedEvent, eventTrigger._routedEventHandler, false /* HandledEventsToo */ ); } else { throw new InvalidOperationException(SR.Get(SRID.TriggersSupportsEventTriggersOnly)); } } //////////////////////////////////////////////////////////////////////// // // DisconnectAllTriggers // // Call DisconnectOneTrigger for each trigger in the Triggers collection. internal static void DisconnectAllTriggers( FrameworkElement triggersHost ) { TriggerCollection triggerCollection = TriggerCollectionField.GetValue(triggersHost); if( triggerCollection != null ) { for( int i = 0; i < triggerCollection.Count; i++ ) { DisconnectOneTrigger( triggersHost, triggerCollection[i] ); } } } //////////////////////////////////////////////////////////////////////// // // DisconnectOneTrigger // // In ProcessOneTrigger, we connect an event trigger to the element // which it targets. Here, we remove the event listener to clean up. internal static void DisconnectOneTrigger( FrameworkElement triggersHost, TriggerBase triggerBase ) { EventTrigger eventTrigger = triggerBase as EventTrigger; if( eventTrigger != null ) { eventTrigger._source.RemoveHandler( eventTrigger.RoutedEvent, eventTrigger._routedEventHandler); eventTrigger._routedEventHandler = null; } else { throw new InvalidOperationException(SR.Get(SRID.TriggersSupportsEventTriggersOnly)); } } internal class EventTriggerSourceListener { internal EventTriggerSourceListener( EventTrigger trigger, FrameworkElement host ) { _owningTrigger = trigger; _owningTriggerHost = host; } internal void Handler(object sender, RoutedEventArgs e) { // Invoke all actions of the associated EventTrigger object. TriggerActionCollection actions = _owningTrigger.Actions; for( int j = 0; j < actions.Count; j++ ) { actions[j].Invoke(_owningTriggerHost); } } private EventTrigger _owningTrigger; private FrameworkElement _owningTriggerHost; } } } // 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
- XMLUtil.cs
- BrowserCapabilitiesCodeGenerator.cs
- TableLayoutRowStyleCollection.cs
- PrintEvent.cs
- StreamSecurityUpgradeAcceptorAsyncResult.cs
- ComNativeDescriptor.cs
- AbstractExpressions.cs
- _NetworkingPerfCounters.cs
- ToggleButton.cs
- RequestUriProcessor.cs
- XmlDesignerDataSourceView.cs
- HttpInputStream.cs
- AttributeEmitter.cs
- Trace.cs
- LineInfo.cs
- DeflateStream.cs
- X509IssuerSerialKeyIdentifierClause.cs
- QuotaExceededException.cs
- BuildProvider.cs
- SoapObjectInfo.cs
- GridSplitterAutomationPeer.cs
- DebugManager.cs
- MouseWheelEventArgs.cs
- ChildrenQuery.cs
- ElementsClipboardData.cs
- ToolBar.cs
- PreservationFileReader.cs
- EventLogPermissionEntry.cs
- ReferenceList.cs
- ClassDataContract.cs
- HttpResponse.cs
- BamlRecordHelper.cs
- KeyBinding.cs
- GeometryConverter.cs
- Soap.cs
- UpdatePanel.cs
- DataServiceQueryException.cs
- OracleParameter.cs
- FixedSOMElement.cs
- MenuItemStyleCollectionEditor.cs
- FileUtil.cs
- CalendarDateRangeChangingEventArgs.cs
- CodeTypeReference.cs
- MetadataFile.cs
- SizeConverter.cs
- MarginsConverter.cs
- SingleAnimationBase.cs
- SettingsProperty.cs
- CacheChildrenQuery.cs
- activationcontext.cs
- TileBrush.cs
- DbgUtil.cs
- ConnectionPool.cs
- GroupByQueryOperator.cs
- RefreshPropertiesAttribute.cs
- CompoundFileDeflateTransform.cs
- ComplexObject.cs
- PropertyChangedEventArgs.cs
- Constraint.cs
- TypefaceMap.cs
- UIElementPropertyUndoUnit.cs
- IPHostEntry.cs
- TypeDelegator.cs
- StructuredProperty.cs
- RefExpr.cs
- Base64Stream.cs
- DbDataReader.cs
- RepeaterItemCollection.cs
- WaitForChangedResult.cs
- _UriSyntax.cs
- ServiceBehaviorElement.cs
- AssociativeAggregationOperator.cs
- ImagingCache.cs
- PoisonMessageException.cs
- Graphics.cs
- CommittableTransaction.cs
- ProtectedConfigurationProviderCollection.cs
- StorageBasedPackageProperties.cs
- SendingRequestEventArgs.cs
- HeaderUtility.cs
- PropertyIDSet.cs
- WinEventTracker.cs
- TypeForwardedToAttribute.cs
- WebPageTraceListener.cs
- followingquery.cs
- WebPartTracker.cs
- PathNode.cs
- SqlMetaData.cs
- FunctionDescription.cs
- SizeConverter.cs
- EntityCommandCompilationException.cs
- DateTimeConverter2.cs
- CodeExpressionCollection.cs
- _OverlappedAsyncResult.cs
- TextSegment.cs
- OracleRowUpdatingEventArgs.cs
- WebBrowserDocumentCompletedEventHandler.cs
- XPathSelectionIterator.cs
- SimpleWebHandlerParser.cs
- ExtractCollection.cs