Revit documents can have links to various external files, including other Revit documents. These types of links in the Revit API are represented by the RevitLinkType and RevitLinkInstance classes. The RevitLinkType class represents another Revit Document ("link") brought into the current one ("host"), while the RevitLinkInstance class represents an instance of a RevitLinkType.
To create a new Revit link, use the static RevitLinkType.Create() method which will create a new Revit link type and load the linked document and the static RevitLinkInstance.Create() method to place an instance of the link in the model. The RevitLinkType.Create() method requires a document (which will be the host), a ModelPath to the file to be linked, and a RevitLinkOptions object. The RevitLinkOptions class represents options for creating and loading a Revit link. Options include whether or not Revit will store a relative or absolute path to the linked file and the workset configuration. The WorksetConfiguration class is used to specify which, if any, worksets will be opened when creating the link. Note that the relative or absolute path determines how Revit will store the path, but the ModelPath passed into the Create() method needs a complete path to find the linked document initially.
The following example demonstrates the use of RevitLinkType.Create(). The variable pathName is the full path to the file on disk to be linked.
Code Region: Create new Revit Link |
public ElementId CreateRevitLink(Document doc, string pathName) { FilePath path = new FilePath(pathName); RevitLinkOptions options = new RevitLinkOptions(false); // Create new revit link storing absolute path to file LinkLoadResult result = RevitLinkType.Create(doc, path, options); return (result.ElementId); } |
Code Region: Create new Revit Link Instance |
public void CreateLinkInstances(Document doc, ElementId linkTypeId) { // Create revit link instance at origin RevitLinkInstance.Create(doc, linkTypeId); RevitLinkInstance instance2 = RevitLinkInstance.Create(doc, linkTypeId); // Offset second instance by 100 feet Location location = instance2.Location; location.Move(new XYZ(0, -100, 0)); } |
Code Region: Create new Revit Link to a model located on Revit server |
public static void CreateLinkToServerModel(UIApplication uiApp) { UIDocument uiDoc = uiApp.ActiveUIDocument; Document doc = uiDoc.Document; // Try to get the server path for the particular model on the server Application application = uiApp.Application; String hostId = application.GetRevitServerNetworkHosts().First(); String rootFolder = "|"; ModelPath serverPath = FindWSAPIModelPathOnServer(application, hostId, rootFolder, "Wall pin model for updaters.rvt"); using (Transaction t = new Transaction(doc, "Create link")) { t.Start(); RevitLinkOptions options = new RevitLinkOptions(false); LinkLoadResult result = RevitLinkType.Create(doc, serverPath, options); RevitLinkInstance.Create(doc, result.ElementId); t.Commit(); } } private static ModelPath FindWSAPIModelPathOnServer(Application app, string hostId, string folderName, string fileName) { // Connect to host to find list of available models (the "/contents" flag) XmlDictionaryReader reader = GetResponse(app, hostId, folderName + "/contents"); bool found = false; // Look for the target model name in top level folder List |
Code Region: Create link with one workset open |
public bool CreateRevitLinkWithOneWorksetOpen(Document doc, string pathName, string worksetName) { FilePath path = new FilePath(pathName); RevitLinkOptions options = new RevitLinkOptions(true); // Get info on all the user worksets in the project prior to opening IList |
Code Region: Getting Link information |
public void GetAllRevitLinkInstances(Document doc) { FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(RevitLinkInstance)); StringBuilder linkedDocs = new StringBuilder(); foreach (Element elem in collector) { RevitLinkInstance instance = elem as RevitLinkInstance; Document linkDoc = instance.GetLinkDocument(); linkedDocs.AppendLine("FileName: " + Path.GetFileName(linkDoc.PathName)); RevitLinkType type = doc.GetElement(instance.GetTypeId()) as RevitLinkType; linkedDocs.AppendLine("Is Nested: " + type.IsNestedLink.ToString()); } TaskDialog.Show("Revit Links in Document", linkedDocs.ToString()); } |
The RevitLinkType methods SavePositions() and HasSaveablePositions() support saving shared coordinates changes back to the linked document. Use HasSaveablePositions() to determine if the link has shared positioning changes which can be saved. Call SavePositions() to save shared coordinates changes back to the linked document. SavePositions() requires an instance of the ISaveSharedCoordinatesCallback interface to resolve situations when Revit encounters modified links. The interface's GetSaveModifiedLinksOption() method determines whether Revit should save the link, not save the link, or discard shared positioning entirely.
While SavePositions() does not clear the document's undo history, it cannot be undone since it saves the link's shared coordinates changes to disk.
The Reference class has members related to linked files that allow conversion between Reference objects which reference only the contents of the link and Reference objects which reference the host. This allows an application, for example, to look at the geometry in the link, find the needed face, and convert the reference to that face into a reference in the host suitable for use to place a face-based instance. Also, these Reference members make it possible to obtain a reference in the host (e.g. from a dimension or family) and convert it to a reference in the link suitable for use in Element.GetGeometryObjectFromReference().
The Reference. LinkedElementId property represents the id of the top-level element in the linked document that is referred to by this reference, or InvalidElementId for references that do not refer to an element in a linked RVT file. The Reference . CreateLinkReference() method uses a RevitLinkInstance to create a Reference from a Reference in a Revit link. And the Reference. CreateReferenceInLink() method creates a Reference in a Revit Link from a Reference in the host file
The Selection methods PickObject() and PickObjects() allow the selection of objects in Revit links. To allow the user to select elements in linked files, use the ObjectType.LinkedElement enumeration value for the first parameter of the PickObject() or PickObjects(). Note that this option allows for selection of elements in links only, not in the host document.
In the example below, an ISelectionFilter is used to allow only walls to be selected in linked files.
Code Region: Selecting Elements in Linked File |
public void SelectElementsInLinkedDoc(Autodesk.Revit.DB.Document document) { UIDocument uidoc = new UIDocument(document); Selection choices = uidoc.Selection; // Pick one wall from Revit link WallInLinkSelectionFilter wallFilter = new WallInLinkSelectionFilter(); Reference elementRef = choices.PickObject(ObjectType.LinkedElement, wallFilter, "Select a wall in a linked document"); if (elementRef != null) { TaskDialog.Show("Revit", "Element from link document selected."); } } // This filter allows selection of only a certain element type in a link instance. class WallInLinkSelectionFilter : ISelectionFilter { private RevitLinkInstance m_currentInstance = null; public bool AllowElement(Element e) { // Accept any link instance, and save the handle for use in AllowReference() m_currentInstance = e as RevitLinkInstance; return (m_currentInstance != null); } public bool AllowReference(Reference refer, XYZ point) { if (m_currentInstance == null) return false; // Get the handle to the element in the link Document linkedDoc = m_currentInstance.GetLinkDocument(); Element elem = linkedDoc.GetElement(refer.LinkedElementId); // Accept the selection if the element exists and is of the correct type return elem != null && elem is Wall; } } |