Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / 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
- LinqDataSource.cs
- PerfService.cs
- CodeDomLoader.cs
- ParameterElement.cs
- XmlMembersMapping.cs
- CancellationHandler.cs
- Rectangle.cs
- InvokeBase.cs
- GeneralTransform3DTo2D.cs
- LinkButton.cs
- PageBreakRecord.cs
- QueryOperatorEnumerator.cs
- Accessible.cs
- TextUtf8RawTextWriter.cs
- DuplexChannelFactory.cs
- MaskDesignerDialog.cs
- DocComment.cs
- SplayTreeNode.cs
- BufferedWebEventProvider.cs
- OdbcFactory.cs
- HtmlTernaryTree.cs
- BufferAllocator.cs
- securitycriticaldata.cs
- ContourSegment.cs
- DNS.cs
- StylusButton.cs
- MSG.cs
- Attachment.cs
- GuidelineSet.cs
- ModulesEntry.cs
- Decoder.cs
- NgenServicingAttributes.cs
- Identifier.cs
- ImageInfo.cs
- Stack.cs
- IconBitmapDecoder.cs
- MergePropertyDescriptor.cs
- ColumnBinding.cs
- TextBoxLine.cs
- HttpRequest.cs
- DelayDesigner.cs
- ImageField.cs
- InputReferenceExpression.cs
- EmptyCollection.cs
- CodeTypeDeclarationCollection.cs
- ControlIdConverter.cs
- SpecularMaterial.cs
- DispatcherSynchronizationContext.cs
- FragmentQueryKB.cs
- DataGridRelationshipRow.cs
- JsonMessageEncoderFactory.cs
- InputMethod.cs
- CompilerState.cs
- IPEndPoint.cs
- ActiveDesignSurfaceEvent.cs
- TextServicesHost.cs
- ObjectStateManager.cs
- SecurityElement.cs
- MembershipSection.cs
- ToolStripItemTextRenderEventArgs.cs
- DateTimeOffsetStorage.cs
- CryptoApi.cs
- AssemblyAttributesGoHere.cs
- FeatureSupport.cs
- JoinElimination.cs
- SHA384.cs
- TypeConverterAttribute.cs
- UserControl.cs
- ButtonPopupAdapter.cs
- SafeArrayRankMismatchException.cs
- DelayedRegex.cs
- InfoCardProofToken.cs
- PolicyUnit.cs
- MatrixTransform.cs
- NumericExpr.cs
- XpsS0ValidatingLoader.cs
- SwitchExpression.cs
- PointAnimationUsingPath.cs
- UInt64.cs
- WindowPattern.cs
- SymbolMethod.cs
- GrammarBuilderWildcard.cs
- SQLByteStorage.cs
- SeekStoryboard.cs
- DownloadProgressEventArgs.cs
- datacache.cs
- _BasicClient.cs
- PanelDesigner.cs
- DesignerCapabilities.cs
- HttpResponse.cs
- _NestedSingleAsyncResult.cs
- DiagnosticTrace.cs
- MissingFieldException.cs
- WmlPageAdapter.cs
- TwoPhaseCommit.cs
- ObjectContext.cs
- RSACryptoServiceProvider.cs
- SByteStorage.cs
- wmiprovider.cs
- ResponseStream.cs