// Get rid of descendant model items when both ancestor and descendant and ancestor model items are selected internal static IEnumerable <ModelItem> GetModelItemsToDrag(IEnumerable <ModelItem> modelItems) { HashSet <ModelItem> modelItemsToDrag = new HashSet <ModelItem>(); foreach (ModelItem modelItem in modelItems) { HashSet <ModelItem> parentModelItems = CutCopyPasteHelper.GetSelectableParentModelItems(modelItem); parentModelItems.IntersectWith(modelItems); if (parentModelItems.Count == 0) { modelItemsToDrag.Add(modelItem); } } return(modelItemsToDrag); }
static void CutCopyOperation(List <ModelItem> modelItemsToCutCopy, EditingContext context, bool isCutOperation) { List <object> objectsOnClipboard = null; List <object> metaData = null; if (modelItemsToCutCopy.Count > 0) { objectsOnClipboard = new List <object>(modelItemsToCutCopy.Count); metaData = new List <object>(); Dictionary <ICompositeView, List <ModelItem> > notifyDictionary = new Dictionary <ICompositeView, List <ModelItem> >(); UIElement breadCrumbRootView = ((DesignerView)context.Services.GetService <DesignerView>()).RootDesigner; foreach (ModelItem modelItem in modelItemsToCutCopy) { object currentElement = modelItem.GetCurrentValue(); if (typeof(Activity).IsAssignableFrom(currentElement.GetType())) { string fileName; if (AttachablePropertyServices.TryGetProperty(currentElement, XamlDebuggerXmlReader.FileNameName, out fileName)) { AttachablePropertyServices.RemoveProperty(currentElement, XamlDebuggerXmlReader.FileNameName); } } if (modelItem.View != null) { //The case where the breadcrumbroot designer is Cut/Copied. We do not delete the root designer, we only copy it. if (breadCrumbRootView.Equals(modelItem.View)) { notifyDictionary.Clear(); objectsOnClipboard.Add(modelItem.GetCurrentValue()); break; } else { ICompositeView container = (ICompositeView)DragDropHelper.GetCompositeView((WorkflowViewElement)modelItem.View); if (container != null) { //If the parent and some of its children are selected and cut/copied, we ignore the children. //The entire parent will be cut/copied. //HashSet parentModelItems contains all the model items in the parent chain of current modelItem. //We use HashSet.IntersectWith operation to determine if one of the parents is set to be cut. HashSet <ModelItem> parentModelItems = CutCopyPasteHelper.GetSelectableParentModelItems(modelItem); parentModelItems.IntersectWith(modelItemsToCutCopy); if (parentModelItems.Count == 0) { if (!notifyDictionary.ContainsKey(container)) { notifyDictionary[container] = new List <ModelItem>(); } notifyDictionary[container].Add(modelItem); } } } } } foreach (ICompositeView container in notifyDictionary.Keys) { object containerMetaData = false; if (isCutOperation) { containerMetaData = container.OnItemsCut(notifyDictionary[container]); } else { containerMetaData = container.OnItemsCopied(notifyDictionary[container]); } if (containerMetaData != null) { metaData.Add(containerMetaData); } //Put the actual activities and not the modelItems in the clipboard. foreach (ModelItem modelItem in notifyDictionary[container]) { objectsOnClipboard.Add(modelItem.GetCurrentValue()); } } if (metaData.Count == 0) { metaData = null; } } try { FrameworkName targetFramework = context.Services.GetService <DesignerConfigurationService>().TargetFrameworkName; PutOnClipBoard(objectsOnClipboard, metaData, targetFramework); } catch (XamlObjectReaderException exception) { if (modelItemsToCutCopy.Count > 0 && ErrorActivity.GetHasErrorActivities(modelItemsToCutCopy[0].Root.GetCurrentValue())) { ErrorReporting.ShowErrorMessage(SR.CutCopyErrorActivityMessage); } else { ErrorReporting.ShowErrorMessage(exception.Message); } } }