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
- StatusBarDesigner.cs
- HttpGetProtocolImporter.cs
- ScrollChrome.cs
- WebPartChrome.cs
- RectAnimationClockResource.cs
- XmlSchemaProviderAttribute.cs
- Path.cs
- RelatedView.cs
- NgenServicingAttributes.cs
- ButtonPopupAdapter.cs
- ListControlDesigner.cs
- WebPartHelpVerb.cs
- PropertyIDSet.cs
- XamlSerializerUtil.cs
- TextParentUndoUnit.cs
- DateTimeSerializationSection.cs
- FixedSOMSemanticBox.cs
- ThrowHelper.cs
- ScrollChrome.cs
- MediaSystem.cs
- InspectionWorker.cs
- TrackingMemoryStreamFactory.cs
- DataGridItem.cs
- Rules.cs
- MonitorWrapper.cs
- TextPattern.cs
- _ReceiveMessageOverlappedAsyncResult.cs
- MsmqBindingElementBase.cs
- UICuesEvent.cs
- LayoutSettings.cs
- MouseEvent.cs
- CustomWebEventKey.cs
- HttpProcessUtility.cs
- TdsParserSessionPool.cs
- XmlSchemas.cs
- DbMetaDataCollectionNames.cs
- OdbcRowUpdatingEvent.cs
- FileDialog.cs
- ExpressionBuilder.cs
- SizeF.cs
- XmlSchemaResource.cs
- Viewport3DAutomationPeer.cs
- WindowsSecurityTokenAuthenticator.cs
- HiddenFieldPageStatePersister.cs
- WhereaboutsReader.cs
- Baml2006ReaderFrame.cs
- CodeCompileUnit.cs
- LiteralTextContainerControlBuilder.cs
- TimeSpan.cs
- XmlSchemaDocumentation.cs
- CopyCodeAction.cs
- filewebresponse.cs
- AccessDataSource.cs
- OracleDataReader.cs
- CellConstant.cs
- SqlFacetAttribute.cs
- SRef.cs
- ControlPropertyNameConverter.cs
- ProfileGroupSettings.cs
- EventlogProvider.cs
- PageThemeParser.cs
- CacheMemory.cs
- HideDisabledControlAdapter.cs
- SqlInternalConnectionSmi.cs
- ImageMapEventArgs.cs
- EventTrigger.cs
- ServiceObjectContainer.cs
- GridViewRowEventArgs.cs
- GridViewItemAutomationPeer.cs
- ConfigurationManagerInternalFactory.cs
- MetadataExporter.cs
- XamlTreeBuilder.cs
- SchemaEntity.cs
- XsltLibrary.cs
- JulianCalendar.cs
- PaperSource.cs
- IHttpResponseInternal.cs
- ConfigXmlText.cs
- CultureSpecificCharacterBufferRange.cs
- SystemIPv6InterfaceProperties.cs
- ImageIndexConverter.cs
- TableHeaderCell.cs
- ResourcePermissionBase.cs
- CleanUpVirtualizedItemEventArgs.cs
- ProcessHost.cs
- TimeoutStream.cs
- PointAnimationBase.cs
- DataQuery.cs
- DbParameterCollection.cs
- HtmlInputFile.cs
- XmlSerializationReader.cs
- SettingsProperty.cs
- UnhandledExceptionEventArgs.cs
- TemplateColumn.cs
- KeyTimeConverter.cs
- SqlServices.cs
- HintTextMaxWidthConverter.cs
- LassoHelper.cs
- RangeValidator.cs
- CubicEase.cs