/// <summary> /// Rescues a Value if it has Valid References /// </summary> /// <param name="valueDeleted">It's the UniqueID of the IStateObject being deleted</param> /// <param name="branchUniqueID">It's the Root object that started the Deletion process.</param> /// <returns>True if the Value had valid references and it was rescued from deletion.</returns> internal bool RescueValue(string objToRemoveUniqueID, string branchUniqueID = null, bool allowUnAttachedReferences = true, bool isDispose = false, IFormBaseViewModel formBaseViewModel = null, HashSet <string> _objectsToBeValidatedAfterDisposeHashSet = null) { if (branchUniqueID == null) { branchUniqueID = objToRemoveUniqueID; } var referencesTable = GetObjectReferencesTable(objToRemoveUniqueID); if (referencesTable != null) { referencesTable.ValidateReferences(branchDeleted: branchUniqueID, validateUnAttached: !allowUnAttachedReferences); //If the object to be removed is a ListItem AND the referencesTable's count is major than zero, //then we have a special block for handling this situation. if (UniqueIDGenerator.IsListItem(objToRemoveUniqueID) && referencesTable.Count > 0) { //If the referenced object is IViewModel, or IDisposableDependencyControl, //we should never rescue them. if (isDispose && referencesTable.IsReferencedObjectAnIDisposableDependencyControl) { return(false); } //If there are some valid references, we should rescue it. else if (HasValidReferencesForListItem(referencesTable, objToRemoveUniqueID, _objectsToBeValidatedAfterDisposeHashSet)) { RescuedValueUniqueIdHashSet.Add(objToRemoveUniqueID); return(true); } //otherwise, we shouldn't resue it else { return(false); } } else if (referencesTable.Count > 0)//No references { bool res = TransferValueToReference(branchUniqueID, referencesTable, isDispose: isDispose, formBaseViewModel: formBaseViewModel); if (res) { RescuedValueUniqueIdHashSet.Add(objToRemoveUniqueID); } return(res); } } //Given this kind of uniqueID: x#y#KIXYZ // We have to validate if KIXYZ has been rescued previously, // if this KIXYZ has been rescued, we should skip this uniqueID var accessPathIndex = objToRemoveUniqueID.LastIndexOf(UniqueIDGenerator.UniqueIdSeparator); if (accessPathIndex > 0) { var ancestorUID = objToRemoveUniqueID.Substring(accessPathIndex + 1); var canRescue = RescuedValueUniqueIdHashSet.Contains(ancestorUID) && !_stateManager.IsInElementsToRemove(ancestorUID); if (UniqueIDGenerator.IsListItem(ancestorUID) && canRescue) { return(true); } } return(false); }
private bool TransferValueToReference(string branchRemoved, ReferencesTable referencesTable, IStateObject elementToAdoptObj = null, bool isDispose = false, IFormBaseViewModel formBaseViewModel = null) { if (isDispose && referencesTable.IsReferencedObjectAnIDisposableDependencyControl) { return(false); } //If the elementToAdopt was not sent as a parameter let's calculate it. if (elementToAdoptObj == null) { elementToAdoptObj = referencesTable.ReferencedObject; } string oldParentUniqueID = elementToAdoptObj.UniqueID; //Entire windows won't be preserved. if (elementToAdoptObj is IViewModel) { return(false); } //Let's get the reference candidate for the adoption. var reference = GetReferenceValidForAdoption(referencesTable, false); if (reference == null) { return(false); } var candidate = CalculateCandidateForAdoption(reference); //The cadidates parent was already removed...Ciao if (candidate == null) { return(false); } bool doNotRegisterIDSwitch = true; if (formBaseViewModel == null) { formBaseViewModel = ViewManager.Instance.GetTopLevelObject(elementToAdoptObj) as IFormBaseViewModel; } if (formBaseViewModel != null) { doNotRegisterIDSwitch = formBaseViewModel.IsDisposing; } if (!(elementToAdoptObj is IDisposableDependencyControl) || (!isDispose && !doNotRegisterIDSwitch)) { //The element won't belong to the parent anymore. IStateObject elementsToBeAdopted = _stateManager.DettachObject(elementToAdoptObj, !doNotRegisterIDSwitch); //We need to promote the object and attach it to the first candidate. AdoptionInformation.StaticAdopt(candidate, elementsToBeAdopted); ////Let's update all the references UpdateReferencesTables(oldParentUniqueID, elementToAdoptObj.UniqueID); //Only foreign references allowed referencesTable.RemoveReference(reference); //We move the element to a substitute parent. referencesTable.AttachedToParent = false; //We had a succesfull adoption :) return(true); } return(false); }