void BringToFront() { FreeFormPanel panel = StateContainerEditor.GetVisualAncestor <FreeFormPanel>(this); // It is possible when BringToFront is executed, the state has already been deleted if (panel != null) { panel.Children.Remove(this); panel.Children.Add(this); // Bring to front all attached connectors including those attached to child states StateContainerEditor parent = StateContainerEditor.GetVisualAncestor <StateContainerEditor>(this); if (parent != null) { FreeFormPanel outmostPanel = parent.GetOutmostStateContainerEditor().Panel; HashSet <Connector> connectors = new HashSet <Connector>(); List <ModelItem> allStateModelItems = new List <ModelItem>(); allStateModelItems.Add(this.ModelItem); allStateModelItems.AddRange(StateContainerEditor.GetAllChildStateModelItems(this.ModelItem)); foreach (ModelItem stateModelItem in allStateModelItems) { List <Connector> attachedConnectors = StateContainerEditor.GetAttachedConnectors((UIElement)stateModelItem.View); foreach (Connector connector in attachedConnectors) { connectors.Add(connector); } } foreach (Connector connector in connectors) { outmostPanel.Children.Remove(connector); outmostPanel.Children.Add(connector); } } } }
void StoreConnectorLocationViewState(Connector connector, bool isUndoableViewState) { //This method will be called whenever the FreeFormPanel raises a location changed event on a connector. //Such location changed events are a result of changes already committed in the UI. Hence we do not want to react to such view state changes. //Using internalViewStateChange flag for that purpose. this.internalViewStateChange = true; this.StoreConnectorLocationViewState(StateContainerEditor.GetConnectorModelItem(connector), connector.Points, isUndoableViewState); this.internalViewStateChange = false; }
public TransitionDesigner() { InitializeComponent(); this.Loaded += (sender, e) => { this.ModelItem.PropertyChanged += OnModelItemPropertyChanged; this.transitionsSharingTrigger.Clear(); ModelItem parentStateModelItem = StateContainerEditor.GetParentStateModelItemForTransition(this.ModelItem); ModelItem triggerModelItem = this.ModelItem.Properties[TriggerPropertyName].Value; if (triggerModelItem != null) { foreach (ModelItem transitionModelItem in parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection) { if (transitionModelItem != this.ModelItem) { if (triggerModelItem == transitionModelItem.Properties[TriggerPropertyName].Value) { this.transitionsSharingTrigger.Add(transitionModelItem); } } } } // Connectors starting from the same point should share the same trigger else { PointCollection thisPointCollection = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerEditor.ConnectorLocationViewStateKey) as PointCollection; if (thisPointCollection != null && thisPointCollection.Count > 1) { foreach (ModelItem transitionModelItem in parentStateModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection) { if (transitionModelItem != this.ModelItem) { PointCollection pointCollection = this.ViewStateService.RetrieveViewState(transitionModelItem, StateContainerEditor.ConnectorLocationViewStateKey) as PointCollection; if (pointCollection != null && pointCollection.Count > 1) { if (pointCollection[0].IsEqualTo(thisPointCollection[0])) { Debug.Assert(transitionModelItem.Properties[TriggerPropertyName].Value == null, "Transition trigger should be null."); this.transitionsSharingTrigger.Add(transitionModelItem); } } } } } } if (this.transitionsSharingTrigger.Count > 0) { this.IsTriggerShared = true; } }; this.Unloaded += (sender, e) => { this.ModelItem.PropertyChanged -= OnModelItemPropertyChanged; this.transitionsSharingTrigger.Clear(); }; }
void DoDeleteItems(List <ModelItem> itemsToDelete, bool removeIncomingConnectors) { HashSet <Connector> connectorsToDelete = new HashSet <Connector>(); List <ModelItem> allStateModelItemsToDelete = new List <ModelItem>(); IEnumerable <ModelItem> selectedStateModelItems = this.Context.Items.GetValue <Selection>().SelectedObjects. Where <ModelItem>((p) => { return(p.ItemType == typeof(State)); }); foreach (ModelItem stateModelItem in itemsToDelete) { allStateModelItemsToDelete.Add(stateModelItem); allStateModelItemsToDelete.AddRange(GetAllChildStateModelItems(stateModelItem)); } foreach (ModelItem modelItem in allStateModelItemsToDelete) { // We only need to delete incoming connectors to the states to be deleted; outgoing connectors will be deleted // automatically when the containing state is deleted. List <Connector> incomingConnectors = StateContainerEditor.GetIncomingConnectors((UIElement)modelItem.View); foreach (Connector connector in incomingConnectors) { ModelItem transitionModelItem = StateContainerEditor.GetConnectorModelItem(connector); // If the transition is contained by the states to delete, we don't bother to delete it separately. if (!StateContainerEditor.IsTransitionModelItemContainedByStateModelItems(transitionModelItem, selectedStateModelItems)) { connectorsToDelete.Add(connector); } } } // If we don't need to remove incoming connectors, we still remove the transitions but then add them back later. // This is in order to create an undo unit that contains the change notifications needed to make undo/redo work correctly. foreach (Connector connector in connectorsToDelete) { ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector); if (removeIncomingConnectors || connectorModelItem.ItemType == typeof(Transition)) { this.DeleteConnectorModelItem(connector); } } if (!removeIncomingConnectors) { foreach (Connector connector in connectorsToDelete) { ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector); if (connectorModelItem.ItemType == typeof(Transition)) { StateContainerEditor.GetParentStateModelItemForTransition(connectorModelItem).Properties[StateDesigner.TransitionsPropertyName].Collection.Add(connectorModelItem); } } } if (null != itemsToDelete) { itemsToDelete.ForEach(p => this.DeleteState(p, removeIncomingConnectors)); } }
internal static List <ConnectionPoint> GetEmptyConnectionPoints(UIElement designer) { List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(designer); if (connectionPoints != null) { return(new List <ConnectionPoint>(connectionPoints.Where <ConnectionPoint>( (p) => { return p.AttachedConnectors == null || p.AttachedConnectors.Count == 0; }))); } return(new List <ConnectionPoint>()); }
void OnStateCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) { StateContainerEditor outmostEditor = this.GetOutmostStateContainerEditor(); if (e.Action == NotifyCollectionChangedAction.Remove) { if (e.OldItems != null) { foreach (ModelItem deleted in e.OldItems) { if (deleted != null) { ModelItemCollection transitions = deleted.Properties[StateDesigner.TransitionsPropertyName].Collection; if (outmostEditor.listenedTransitionCollections.Contains(transitions)) { transitions.CollectionChanged -= new NotifyCollectionChangedEventHandler(outmostEditor.OnTransitionCollectionChanged); outmostEditor.listenedTransitionCollections.Remove(transitions); } if (this.modelItemToUIElement.ContainsKey(deleted)) { this.RemoveStateVisual(this.modelItemToUIElement[deleted] as WorkflowViewElement); } } } } } else if (e.Action == NotifyCollectionChangedAction.Add) { if (e.NewItems != null) { foreach (ModelItem added in e.NewItems) { if (added != null) { ModelItemCollection transitions = added.Properties[StateDesigner.TransitionsPropertyName].Collection; if (!outmostEditor.listenedTransitionCollections.Contains(transitions)) { transitions.CollectionChanged += new NotifyCollectionChangedEventHandler(outmostEditor.OnTransitionCollectionChanged); outmostEditor.listenedTransitionCollections.Add(transitions); } this.AddStateVisuals(new List <ModelItem> { added }); } } } } }
public object OnItemsCopied(List <ModelItem> itemsToCopy) { // Save the locations of copied items relative to the outmost editor to the metadata. // The metadata will be used to translate the location view states of pasted items to the pasting target. PointCollection metaData = new PointCollection(); foreach (ModelItem modelItem in itemsToCopy) { object viewState = this.ViewStateService.RetrieveViewState(modelItem, ShapeLocationViewStateKey); Point location = (Point)viewState; StateContainerEditor parentDesigner = StateContainerEditor.GetVisualAncestor <StateContainerEditor>(modelItem.View); location = parentDesigner.panel.GetLocationRelativeToOutmostPanel(location); metaData.Add(location); } return(metaData); }
protected override void OnMouseMove(MouseEventArgs args) { base.OnMouseMove(args); if (args != null && !this.Disabled) { if (args.LeftButton == MouseButtonState.Pressed && this.IsMouseCaptured) { StateContainerEditor stateContainerEditor = this.ParentStateContainerEditor; FreeFormPanel panel = stateContainerEditor.Panel; Grid stateContainerGrid = stateContainerEditor.stateContainerGrid; Point currentPosition = Mouse.GetPosition(stateContainerGrid); currentPosition.Offset(this.offset.X, this.offset.Y); stateContainerEditor.StateContainerWidth = Math.Min(Math.Max(panel.RequiredWidth, currentPosition.X), stateContainerGrid.MaxWidth); stateContainerEditor.StateContainerHeight = Math.Min(Math.Max(panel.RequiredHeight, currentPosition.Y), stateContainerGrid.MaxHeight); } } }
internal void DeleteConnectorModelItem(Connector connector) { ModelItem connectorModelItem = StateContainerEditor.GetConnectorModelItem(connector); if (connectorModelItem.ItemType == typeof(Transition)) { StateContainerEditor.GetParentStateModelItemForTransition(connectorModelItem).Properties[StateDesigner.TransitionsPropertyName].Collection.Remove(connectorModelItem); } // Connector from initial node else if (connectorModelItem.ItemType == typeof(StateMachine)) { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.ClearInitialState)) { connectorModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(null); es.Complete(); } } }
static ConnectionPoint ConnectionPointHitTest(UIElement element, Point hitPoint) { ConnectionPoint hitConnectionPoint = null; List <ConnectionPoint> connectionPoints = StateContainerEditor.GetConnectionPoints(element); foreach (ConnectionPoint connPoint in connectionPoints) { if (connPoint != null) { // We need to transform the connection point location to be relative to the outmost panel FreeFormPanel panel = GetVisualAncestor <FreeFormPanel>(element); if (new Rect(panel.GetLocationRelativeToOutmostPanel(connPoint.Location) + connPoint.HitTestOffset, connPoint.HitTestSize).Contains(hitPoint)) { hitConnectionPoint = connPoint; break; } } } return(hitConnectionPoint); }
void UpdateLocationViewStatesByMetaData(List <ModelItem> itemsPasted, List <object> metaData) { // If the states are not copied from state machine view (e.g., when the State designer is the breadcrumb root), // there is no meta data if (metaData != null && metaData.Count > 0) { StateContainerEditor outmostEditor = this.GetOutmostStateContainerEditor(); int ii = 0; foreach (object data in metaData) { PointCollection points = (PointCollection)data; foreach (Point point in points) { // translate location view states to be in the coordinate system of the pasting target this.ViewStateService.StoreViewState(itemsPasted[ii], ShapeLocationViewStateKey, outmostEditor.panel.TranslatePoint(point, this.panel)); ++ii; } } Debug.Assert(itemsPasted.Count == ii, "itemsCopied does not match the metaData."); } }
// All the connectors are directly contained by the outmost editor. This is because connectors can go across states. void OnEditingScopeCompleted(object sender, EditingScopeEventArgs e) { Debug.Assert(this.IsOutmostStateContainerEditor(), "Only the outmost editor should listen to the EditingScopeCompleted events of the model tree."); if (this.transitionModelItemsAdded.Count > 0) { // We need to wait until after the state visuals are updated this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { foreach (ModelItem transition in this.transitionModelItemsAdded) { ModelItem srcStateModelItem = StateContainerEditor.GetParentStateModelItemForTransition(transition); this.AddTransitionVisual(transition); } this.transitionModelItemsAdded.Clear(); })); } if (this.initialStateChanged) { Debug.Assert(this.ModelItem.ItemType == typeof(StateMachine), "Only StateMachine should have initial state"); Debug.Assert(this.initialNode != null, "Initial node should not be null"); // Remove the old link if (GetAttachedConnectors(this.initialNode).Count > 0) { this.RemoveConnectorOnOutmostEditor(GetAttachedConnectors(this.initialNode)[0]); } // Add the new link if the new initial state is not null ModelItem initialStateModelItem = this.ModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].Value; if (initialStateModelItem != null) { // We need to wait until after the state visuals are updated this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { this.AddInitialNodeConnector(); })); } this.initialStateChanged = false; } }
void OnStateContainerLoaded(object sender, RoutedEventArgs e) { this.stateContainerEditor = sender as StateContainerEditor; }
void System.Windows.Markup.IComponentConnector.Connect(int connectionId, object target) { switch (connectionId) { case 1: this.stateContainerEditor = ((Wxwinter.BPM.Machine.Design.StateContainerEditor)(target)); return; case 2: this.stateContainerGrid = ((System.Windows.Controls.Grid)(target)); #line 27 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.MouseLeave += new System.Windows.Input.MouseEventHandler(this.OnStateContainerGridMouseLeave); #line default #line hidden #line 27 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.MouseMove += new System.Windows.Input.MouseEventHandler(this.OnStateContainerGridMouseMove); #line default #line hidden #line 27 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.PreviewMouseMove += new System.Windows.Input.MouseEventHandler(this.OnStateContainerGridPreviewMouseMove); #line default #line hidden #line 28 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.PreviewMouseUp += new System.Windows.Input.MouseButtonEventHandler(this.OnStateContainerGridPreviewMouseUp); #line default #line hidden #line 28 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.KeyDown += new System.Windows.Input.KeyEventHandler(this.OnStateContainerGridKeyDown); #line default #line hidden #line 28 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.PreviewMouseDown += new System.Windows.Input.MouseButtonEventHandler(this.OnStateContainerGridPreviewMouseDown); #line default #line hidden #line 29 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.DragOver += new System.Windows.DragEventHandler(this.OnStateContainerGridDragOver); #line default #line hidden #line 29 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.DragEnter += new System.Windows.DragEventHandler(this.OnStateContainerGridDragEnter); #line default #line hidden #line 29 "..\..\StateContainerEditor.xaml" this.stateContainerGrid.Drop += new System.Windows.DragEventHandler(this.OnStateContainerGridDrop); #line default #line hidden return; case 3: this.panel = ((Wxwinter.BPM.Machine.Design.FreeFormEditing.FreeFormPanel)(target)); return; } this._contentLoaded = true; }
void Populate() { // Keep track of the outmost editor, which may not be accessible by traversing the visual tree when the designer is deleted. this.outmostStateContainerEditor = this.GetOutmostStateContainerEditor(); this.panel.LocationChanged += new LocationChangedEventHandler(OnFreeFormPanelLocationChanged); this.panel.ConnectorMoved += new ConnectorMovedEventHandler(OnFreeFormPanelConnectorMoved); this.panel.LayoutUpdated += new EventHandler(OnFreeFormPanelLayoutUpdated); this.panel.RequiredSizeChanged += new RequiredSizeChangedEventHandler(OnFreeFormPanelRequiredSizeChanged); this.ViewStateService.ViewStateChanged += new ViewStateChangedEventHandler(OnViewStateChanged); this.ModelItem.Properties[ChildStatesPropertyName].Collection.CollectionChanged += new NotifyCollectionChangedEventHandler(OnStateCollectionChanged); this.ModelItem.PropertyChanged += new PropertyChangedEventHandler(this.OnModelPropertyChanged); ModelTreeManager modelTreeManager = this.Context.Services.GetService<ModelTreeManager>(); modelTreeManager.EditingScopeCompleted += new EventHandler<EditingScopeEventArgs>(this.outmostStateContainerEditor.OnEditingScopeCompleted); if (this.ModelItem.ItemType == typeof(State)) { ModelItemCollection transitions = this.ModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection; if (!this.outmostStateContainerEditor.listenedTransitionCollections.Contains(transitions)) { transitions.CollectionChanged += new NotifyCollectionChangedEventHandler(this.outmostStateContainerEditor.OnTransitionCollectionChanged); this.outmostStateContainerEditor.listenedTransitionCollections.Add(transitions); } } object widthViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerWidthViewStateKey); if (widthViewState != null) { this.StateContainerWidth = (double)widthViewState; } object heightViewState = this.ViewStateService.RetrieveViewState(this.ModelItem, StateContainerHeightViewStateKey); if (heightViewState != null) { this.StateContainerHeight = (double)heightViewState; } panel.Children.Clear(); this.modelItemToUIElement.Clear(); this.shapeLocations.Clear(); this.AddStateVisuals(this.ModelItem.Properties[ChildStatesPropertyName].Collection); if (this.ModelItem.ItemType == typeof(StateMachine)) { this.AddInitialNode(); } // We need to wait until after the state visuals are added and displayed. this.Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => { if (this.ModelItem.ItemType == typeof(State)) { this.AddChildTransitionVisualsToOutmostEditor(); ModelItem stateMachineModelItem = StateContainerEditor.GetStateMachineModelItem(this.ModelItem); if (stateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].Value == this.ModelItem) { this.outmostStateContainerEditor.AddInitialNodeConnector(); } } })); }
// referenceConnector is used when we are re-linking the connector. internal ConnectorCreationResult CreateConnectorGesture(ConnectionPoint sourceConnectionPoint, ConnectionPoint destConnectionPoint, Connector referenceConnector, bool isConnectorStartMoved) { Debug.Assert(this.IsOutmostStateContainerEditor(), "Should only be called by the outmost editor."); Debug.Assert(sourceConnectionPoint != null, "sourceConnectionPoint is null."); Debug.Assert(destConnectionPoint != null, "destConnectionPoint is null."); ConnectorCreationResult result = ConnectorCreationResult.OtherFailure; if (destConnectionPoint.PointType != ConnectionPointType.Outgoing && sourceConnectionPoint.PointType != ConnectionPointType.Incoming) { if (sourceConnectionPoint.ParentDesigner is StateDesigner) { bool sameDestination = false; ModelItem refTransitionModelItem = null; if (referenceConnector != null) { refTransitionModelItem = StateContainerEditor.GetConnectorModelItem(referenceConnector); ModelItem destStateModelItem = ((StateDesigner)destConnectionPoint.ParentDesigner).ModelItem; if (refTransitionModelItem != null && refTransitionModelItem.Properties[TransitionDesigner.ToPropertyName].Value == destStateModelItem) { sameDestination = true; } } // We do not allow transitions to composite states unless we don't change the transition destination // (e.g., we are moving the start of a connector). if (!sameDestination && !((StateDesigner)destConnectionPoint.ParentDesigner).IsSimpleState()) { result = ConnectorCreationResult.CannotCreateTransitionToCompositeState; } // We do not allow transitions from an ancestor to its descendant else if (StateContainerEditor.IsDescendantStateOf(((StateDesigner)destConnectionPoint.ParentDesigner).ModelItem, ((StateDesigner)sourceConnectionPoint.ParentDesigner).ModelItem)) { result = ConnectorCreationResult.CannotCreateTransitionFromAncestorToDescendant; } else { using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.CreateTransition)) { if (refTransitionModelItem != null) { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, refTransitionModelItem, isConnectorStartMoved); } else { this.CreateTransition(sourceConnectionPoint, destConnectionPoint, null, false); } result = ConnectorCreationResult.Success; es.Complete(); } } } else if (sourceConnectionPoint.ParentDesigner is InitialNode) { StateDesigner destDesigner = (StateDesigner)destConnectionPoint.ParentDesigner; // We only allow simple states to be set as the initial state if (!destDesigner.IsSimpleState()) { result = ConnectorCreationResult.CannotSetCompositeStateAsInitialState; } else if (destDesigner.IsFinalState()) { result = ConnectorCreationResult.CannotSetFinalStateAsInitialState; } else { ModelItem destModelItem = destDesigner.ModelItem; using (EditingScope es = (EditingScope)this.ModelItem.BeginEdit(SR.SetInitialState)) { this.StateMachineModelItem.Properties[StateMachineDesigner.InitialStatePropertyName].SetValue(destModelItem); PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnectionPoint, destConnectionPoint)); this.StoreConnectorLocationViewState(this.StateMachineModelItem, connectorViewState, true); result = ConnectorCreationResult.Success; es.Complete(); } } } } return(result); }
//This returns the closest non-outgoing connectionPoint on dest. Return value will be different than sourceConnectionPoint. static ConnectionPoint GetClosestDestConnectionPoint(ConnectionPoint sourceConnectionPoint, UIElement dest) { ConnectionPoint destConnectionPoint = null; if (sourceConnectionPoint.PointType != ConnectionPointType.Incoming) { destConnectionPoint = GetClosestConnectionPointNotOfType(sourceConnectionPoint, StateContainerEditor.GetConnectionPoints(dest), ConnectionPointType.Outgoing); } return(destConnectionPoint); }
//This returns the closest non-incoming connectionPoint on source. Return value will be different than destConnectionPoint. static ConnectionPoint GetClosestSrcConnectionPoint(UIElement src, ConnectionPoint destConnectionPoint) { ConnectionPoint srcConnectionPoint = null; if (destConnectionPoint.PointType != ConnectionPointType.Outgoing) { srcConnectionPoint = GetClosestConnectionPointNotOfType(destConnectionPoint, StateContainerEditor.GetConnectionPoints(src), ConnectionPointType.Incoming); } return(srcConnectionPoint); }
// referenceTransitionModelItem is used when a connector is re-linked. void CreateTransition(ConnectionPoint sourceConnPoint, ConnectionPoint destConnPoint, ModelItem referenceTransitionModelItem, bool isSourceMoved) { Debug.Assert(this.IsOutmostStateContainerEditor(), "Should only be called by the outmost editor."); WorkflowViewElement srcDesigner = sourceConnPoint.ParentDesigner as WorkflowViewElement; WorkflowViewElement destDesigner = destConnPoint.ParentDesigner as WorkflowViewElement; Debug.Assert(srcDesigner is StateDesigner && destDesigner is StateDesigner, "The source and destination designers should both be StateDesigner"); ModelItem srcModelItem = srcDesigner.ModelItem; ModelItem destModelItem = destDesigner.ModelItem; ModelItem transitionModelItem = null; // We are moving the connector. if (referenceTransitionModelItem != null && referenceTransitionModelItem.ItemType == typeof(Transition)) { transitionModelItem = referenceTransitionModelItem; // We are moving the start of the connector. We only preserve the trigger if it is not shared. if (isSourceMoved) { Transition referenceTransition = referenceTransitionModelItem.GetCurrentValue() as Transition; ModelItem stateModelItem = GetParentStateModelItemForTransition(referenceTransitionModelItem); State state = stateModelItem.GetCurrentValue() as State; bool isTriggerShared = false; foreach (Transition transition in state.Transitions) { if (transition != referenceTransition && transition.Trigger == referenceTransition.Trigger) { isTriggerShared = true; break; } } if (isTriggerShared) { transitionModelItem.Properties[TransitionDesigner.TriggerPropertyName].SetValue(null); } } transitionModelItem.Properties[TransitionDesigner.ToPropertyName].SetValue(destModelItem); srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(transitionModelItem); } // We are creating a new connector. else { Transition newTransition = new Transition() { DisplayName = string.Empty }; newTransition.To = destModelItem.GetCurrentValue() as State; // Assign the shared trigger. if (sourceConnPoint.AttachedConnectors.Count > 0) { Connector connector = sourceConnPoint.AttachedConnectors[0]; Transition existingTransition = StateContainerEditor.GetConnectorModelItem(connector).GetCurrentValue() as Transition; newTransition.Trigger = existingTransition.Trigger; } transitionModelItem = srcModelItem.Properties[StateDesigner.TransitionsPropertyName].Collection.Add(newTransition); } if (transitionModelItem != null) { PointCollection connectorViewState = new PointCollection(ConnectorRouter.Route(this.panel, sourceConnPoint, destConnPoint)); this.StoreConnectorLocationViewState(transitionModelItem, connectorViewState, true); } }