/// <summary>
/// Renames the file in the hierarchy by removing old node and adding a new node in the hierarchy.
/// </summary>
/// <param name="oldFileName">The old file name.</param>
/// <param name="newFileName">The new file name</param>
/// <param name="newParentId">The new parent id of the item.</param>
/// <returns>The newly added FileNode.</returns>
/// <remarks>While a new node will be used to represent the item, the underlying MSBuild item will be the same and as a result file properties saved in the project file will not be lost.</remarks>
protected virtual FileNode RenameFileNode(string oldFileName, string newFileName, uint newParentId)
{
if (string.Compare(oldFileName, newFileName, StringComparison.Ordinal) == 0)
{
// We do not want to rename the same file
return(null);
}
this.OnItemDeleted();
this.Parent.RemoveChild(this);
// Since this node has been removed all of its state is zombied at this point
// Do not call virtual methods after this point since the object is in a deleted state.
string[] file = new string[1];
file[0] = newFileName;
VSADDRESULT[] result = new VSADDRESULT[1];
Guid emptyGuid = Guid.Empty;
ErrorHandler.ThrowOnFailure(this.ProjectMgr.AddItemWithSpecific(newParentId, VSADDITEMOPERATION.VSADDITEMOP_OPENFILE, null, 0, file, IntPtr.Zero, 0, ref emptyGuid, null, ref emptyGuid, result));
FileNode childAdded = this.ProjectMgr.FindChild(newFileName) as FileNode;
Debug.Assert(childAdded != null, "Could not find the renamed item in the hierarchy");
// Update the itemid to the newly added.
this.ID = childAdded.ID;
// Remove the item created by the add item. We need to do this otherwise we will have two items.
// Please be aware that we have not removed the ItemNode associated to the removed file node from the hierrachy.
// What we want to achieve here is to reuse the existing build item.
// We want to link to the newly created node to the existing item node and addd the new include.
//temporarily keep properties from new itemnode since we are going to overwrite it
string newInclude = childAdded.ItemNode.Item.EvaluatedInclude;
string dependentOf = childAdded.ItemNode.GetMetadata(ProjectFileConstants.DependentUpon);
childAdded.ItemNode.RemoveFromProjectFile();
// Assign existing msbuild item to the new childnode
childAdded.ItemNode = this.ItemNode;
childAdded.ItemNode.Item.ItemType = this.ItemNode.ItemName;
childAdded.ItemNode.Item.Xml.Include = newInclude;
if (!string.IsNullOrEmpty(dependentOf))
{
childAdded.ItemNode.SetMetadata(ProjectFileConstants.DependentUpon, dependentOf);
}
childAdded.ItemNode.RefreshProperties();
//Update the new document in the RDT.
DocumentManager.RenameDocument(this.ProjectMgr.Site, oldFileName, newFileName, childAdded.ID);
//Select the new node in the hierarchy
IVsUIHierarchyWindow uiWindow = UIHierarchyUtilities.GetUIHierarchyWindow(this.ProjectMgr.Site, SolutionExplorer);
// This happens in the context of renaming a file.
// Since we are already in solution explorer, it is extremely unlikely that we get a null return.
// If we do, the consequences are minimal: the parent node will be selected instead of the
// renamed node.
if (uiWindow != null)
{
ErrorHandler.ThrowOnFailure(uiWindow.ExpandItem(this.ProjectMgr, this.ID, EXPANDFLAGS.EXPF_SelectItem));
}
//Update FirstChild
childAdded.FirstChild = this.FirstChild;
//Update ChildNodes
SetNewParentOnChildNodes(childAdded);
RenameChildNodes(childAdded);
return(childAdded);
}