// The logic is similar to UpdateCloneReferences.
        // the difference is in this function, we need to set reference by Property.
        void UpdateCloneReferenceByModelItem (FlowNode currentFlowElement,
            Dictionary<FlowNode, ModelItem> modelItems, Dictionary<FlowNode, FlowNode> clonedFlowElements)
        {
            if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowStep currentFlowStep = (FlowStep)currentFlowElement;
                FlowStep clonedFlowStep = (FlowStep)clonedFlowElements[currentFlowElement];
                ModelItem modelItem = modelItems[clonedFlowStep];
                FlowNode nextFlowElement = currentFlowStep.Next;
                if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement))
                {
                    modelItem.Properties["Next"].SetValue(clonedFlowElements[nextFlowElement]);
                }
                else
                {
                    modelItem.Properties["Next"].SetValue(null);
                }
            }
            else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType()))
            {
                if (!modelItems.ContainsKey(currentFlowElement))
                {
                    Fx.Assert("Should not happen.");
                }
                FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement;
                FlowDecision clonedFlowDecision = (FlowDecision)clonedFlowElements[currentFlowElement];
                Fx.Assert(currentFlowDecision == clonedFlowDecision, "should not happen");
                ModelItem modelItem = modelItems[currentFlowElement];
                Fx.Assert(modelItem != null, "should not happen");
                FlowNode trueElement = currentFlowDecision.True;
                FlowNode falseElement = currentFlowDecision.False;

                if (trueElement != null && clonedFlowElements.ContainsKey(trueElement))
                {
                    modelItem.Properties["True"].SetValue(clonedFlowElements[trueElement]);
                }
                else
                {
                    modelItem.Properties["True"].SetValue(null);
                }

                if (falseElement != null && clonedFlowElements.ContainsKey(falseElement))
                {
                    modelItem.Properties["False"].SetValue(clonedFlowElements[falseElement]);
                }
                else
                {
                    modelItem.Properties["False"].SetValue(null);
                }

            }
            else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType()))
            {
                GenericFlowSwitchHelper.ReferenceCopy(currentFlowElement.GetType().GetGenericArguments()[0],
                    currentFlowElement,
                    modelItems,
                    clonedFlowElements);
            }
            else
            {
                Debug.Fail("Unknown FlowNode");
            }
        }
        //This does a shallow copy of all the public properties with getter and setter. 
        //It also replicates Xaml Attached properties.
        FlowNode CloneFlowElement(FlowNode flowElement, Predicate<AttachableMemberIdentifier> allowAttachableProperty = null)
        {
            Type flowElementType = flowElement.GetType();
            FlowNode clonedObject = (FlowNode)Activator.CreateInstance(flowElementType);
            foreach (PropertyInfo propertyInfo in flowElementType.GetProperties())
            {
                if (propertyInfo.GetGetMethod() != null && propertyInfo.GetSetMethod() != null)
                {
                    propertyInfo.SetValue(clonedObject, propertyInfo.GetValue(flowElement, null), null);
                }
            }

            //Replicate any Xaml Attached Property.
            KeyValuePair<AttachableMemberIdentifier, object>[] attachedProperties = new KeyValuePair<AttachableMemberIdentifier, object>[AttachablePropertyServices.GetAttachedPropertyCount(flowElement)];
            AttachablePropertyServices.CopyPropertiesTo(flowElement, attachedProperties, 0);
            foreach (KeyValuePair<AttachableMemberIdentifier, object> attachedProperty in attachedProperties)
            {
                if (allowAttachableProperty != null && !allowAttachableProperty(attachedProperty.Key))
                {
                    continue;
                }
                AttachablePropertyServices.SetProperty(clonedObject, attachedProperty.Key, attachedProperty.Value);
            }

            return clonedObject;
        }
        //This method updates the clone of currentFlowElement to reference cloned FlowElements.
        void UpdateCloneReferences(FlowNode currentFlowElement, Dictionary<FlowNode, FlowNode> clonedFlowElements)
        {
            if (typeof(FlowStep).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowStep currentFlowStep = (FlowStep)currentFlowElement;
                FlowStep clonedFlowStep = (FlowStep)clonedFlowElements[currentFlowElement];
                FlowNode nextFlowElement = currentFlowStep.Next;
                if (nextFlowElement != null && clonedFlowElements.ContainsKey(nextFlowElement))
                {
                    clonedFlowStep.Next = clonedFlowElements[nextFlowElement];
                }
                else
                {
                    clonedFlowStep.Next = null;
                }
            }
            else if (typeof(FlowDecision).IsAssignableFrom(currentFlowElement.GetType()))
            {
                FlowDecision currentFlowDecision = (FlowDecision)currentFlowElement;
                FlowDecision clonedFlowDecision = (FlowDecision)clonedFlowElements[currentFlowElement];
                FlowNode trueElement = currentFlowDecision.True;
                FlowNode falseElement = currentFlowDecision.False;

                if (trueElement != null && clonedFlowElements.ContainsKey(trueElement))
                {
                    clonedFlowDecision.True = clonedFlowElements[trueElement];
                }
                else
                {
                    clonedFlowDecision.True = null;
                }

                if (falseElement != null && clonedFlowElements.ContainsKey(falseElement))
                {
                    clonedFlowDecision.False = clonedFlowElements[falseElement];
                }
                else
                {
                    clonedFlowDecision.False = null;
                }

            }
            else if (GenericFlowSwitchHelper.IsGenericFlowSwitch(currentFlowElement.GetType()))
            {
                GenericFlowSwitchHelper.Copy(currentFlowElement.GetType().GetGenericArguments()[0], currentFlowElement, clonedFlowElements);
            }
            else
            {
                Debug.Fail("Unknown FlowNode");
            }
        }