Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / 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.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ConvertersCollection.cs
- ListenerConstants.cs
- CodeArrayCreateExpression.cs
- CursorInteropHelper.cs
- DbParameterHelper.cs
- GeometryGroup.cs
- DivideByZeroException.cs
- CodePageUtils.cs
- TypeConverterAttribute.cs
- PathFigure.cs
- ManifestBasedResourceGroveler.cs
- PeerMaintainer.cs
- TemplateParser.cs
- CodeSnippetCompileUnit.cs
- ListBoxItem.cs
- EdmRelationshipNavigationPropertyAttribute.cs
- Attributes.cs
- ToolBarButtonDesigner.cs
- TextAutomationPeer.cs
- DeploymentSection.cs
- CodeAttributeArgumentCollection.cs
- StrongNameMembershipCondition.cs
- PolicyValidationException.cs
- AutomationPropertyInfo.cs
- BufferModeSettings.cs
- Selection.cs
- HttpListenerRequestUriBuilder.cs
- Ipv6Element.cs
- Highlights.cs
- TdsParserStaticMethods.cs
- RowUpdatingEventArgs.cs
- ActionFrame.cs
- StoreContentChangedEventArgs.cs
- ErrorTableItemStyle.cs
- Transform3DCollection.cs
- JsonDeserializer.cs
- CodeTypeParameterCollection.cs
- ClearCollection.cs
- ServiceBusyException.cs
- PerformanceCounterManager.cs
- SubMenuStyle.cs
- ProviderConnectionPointCollection.cs
- FrameworkRichTextComposition.cs
- BitmapEffectDrawing.cs
- DBProviderConfigurationHandler.cs
- FixedSOMTextRun.cs
- CacheRequest.cs
- UIElementParagraph.cs
- GeometryHitTestParameters.cs
- ProxyWebPartManager.cs
- PrinterUnitConvert.cs
- CompiledAction.cs
- Base64Encoder.cs
- DesignerSerializerAttribute.cs
- Pts.cs
- PhoneCallDesigner.cs
- FormatControl.cs
- SID.cs
- CroppedBitmap.cs
- TextFormatterHost.cs
- TaskCanceledException.cs
- FirstMatchCodeGroup.cs
- ProfileGroupSettings.cs
- IDReferencePropertyAttribute.cs
- MergeExecutor.cs
- EntityContainerEntitySet.cs
- SplashScreenNativeMethods.cs
- WebPartActionVerb.cs
- SqlColumnizer.cs
- WebBrowser.cs
- EdmFunction.cs
- DataViewSetting.cs
- LoginCancelEventArgs.cs
- KnowledgeBase.cs
- XmlLangPropertyAttribute.cs
- CustomTypeDescriptor.cs
- PathGeometry.cs
- PropertyBuilder.cs
- NotifyIcon.cs
- KnownBoxes.cs
- ChannelEndpointElement.cs
- SqlDataSourceCommandEventArgs.cs
- Columns.cs
- TraceUtility.cs
- Column.cs
- CustomErrorCollection.cs
- EmissiveMaterial.cs
- _FtpDataStream.cs
- DataGridViewComboBoxColumn.cs
- TextParentUndoUnit.cs
- SubqueryTrackingVisitor.cs
- WindowHideOrCloseTracker.cs
- SoapServerMethod.cs
- DocumentSequenceHighlightLayer.cs
- XmlSchemaAnnotated.cs
- SafeIUnknown.cs
- InputLanguageProfileNotifySink.cs
- SelectionPatternIdentifiers.cs
- ConfigurationConverterBase.cs
- ListItemCollection.cs