public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument _uidoc = uiapp.ActiveUIDocument; Autodesk.Revit.ApplicationServices.Application _app = uiapp.Application; Autodesk.Revit.DB.Document _doc = _uidoc.Document; BuiltInCategory bicFamilyA = BuiltInCategory.OST_DuctTerminal; BuiltInCategory bicFamilyB = BuiltInCategory.OST_DataDevices; BuiltInCategory bicFamilyC = BuiltInCategory.OST_MechanicalEquipment; //BuiltInCategory bicFamilyC = BuiltInCategory.OST_Sprinklers; ICollection <BuiltInCategory> categories = new[] { bicFamilyA, bicFamilyB, bicFamilyC }; ElementFilter myPCatFilter = new ElementMulticategoryFilter(categories); ISelectionFilter myPickFilter = SelFilter.GetElementFilter(myPCatFilter); bool keepOnTruckn = true; FormMsgWPF formMsg = new FormMsgWPF(); formMsg.Show(); using (TransactionGroup pickGrp = new TransactionGroup(_doc)) { pickGrp.Start("CmdCycleType"); bool firstTime = true; //string strCats= ""; //foreach (BuiltInCategory iCat in categories) { // strCats = strCats + iCat.ToString().Replace("OST_", "") + ", "; //} string strCats = FamilyUtils.BICListMsg(categories); formMsg.SetMsg("Pick the " + strCats + " to check its type.", "Type Cycle:"); while (keepOnTruckn) { try { Reference pickedElemRef = _uidoc.Selection.PickObject(ObjectType.Element, myPickFilter, "Pick the " + bicFamilyA.ToString() + " to cycle its types. (Press ESC to cancel)"); Element pickedElem = _doc.GetElement(pickedElemRef.ElementId); FamilyInstance fi = pickedElem as FamilyInstance; FamilySymbol fs = fi.Symbol; var famTypesIds = fs.Family.GetFamilySymbolIds().OrderBy(e => _doc.GetElement(e).Name).ToList(); int thisIndx = famTypesIds.FindIndex(e => e == fs.Id); int nextIndx = thisIndx; if (!firstTime) { nextIndx = nextIndx + 1; if (nextIndx >= famTypesIds.Count) { nextIndx = 0; } } else { firstTime = false; } if (pickedElem != null) { using (Transaction tp = new Transaction(_doc, "PlunkOMatic:SetParam")) { tp.Start(); if (pickedElem != null) { fi.Symbol = _doc.GetElement(famTypesIds[nextIndx]) as FamilySymbol; formMsg.SetMsg("Currently:\n" + fi.Symbol.Name + "\n\nPick again to cycle its types.", "Type Cycling"); } tp.Commit(); } } else { keepOnTruckn = false; } } catch (Exception) { keepOnTruckn = false; //throw; } } pickGrp.Assimilate(); } formMsg.Close(); return(Result.Succeeded); }
// Family Name and Family Symbol(ie Type) being specified // FindFamilyType(_doc, typeof(FamilySymbol), _FamilyTagName, _FamilyTagNameSymb, _bicTagBeing) // find an element of the given type, name, and category(optional) public static Element FindFamilyType(Autodesk.Revit.DB.Document rvtDoc, Type targetType, string targetFamilyName, string targetTypeName, Nullable <BuiltInCategory> targetCategory) { // Narrow down to elements of the given type and category var collector = new FilteredElementCollector(rvtDoc).OfClass(targetType); // the optional argument if (targetCategory.HasValue) { collector.OfCategory(targetCategory.Value); } // Using LINQ query extract for family name and family type var targetElems = from element in collector where element.Name.Equals(targetTypeName) && element.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString().Equals(targetFamilyName) select element; // put result as list of element for accessing IList <Element> elems = targetElems.ToList(); if (elems.Count > 0) { // Done, exit with the desired element. return(elems.FirstOrDefault()); } // Attempt at this point to find and load the family. Then check if it has the type needed. FormMsgWPF formMsgWPF = new FormMsgWPF(); string msg = "Family Load Needed For: " + targetFamilyName + " having a type: " + targetTypeName; formMsgWPF.SetMsg(msg, "Attempting To Find On Network", " "); formMsgWPF.Show(); List <string> candidates = FindFamilyCandidates(rvtDoc, targetFamilyName); formMsgWPF.Close(); string foundFamPath = candidates.FirstOrDefault(); if (foundFamPath != null) { // sometimes we have a transaction already going on. if (rvtDoc.IsModifiable) { rvtDoc.LoadFamily(foundFamPath); } else { using (Transaction tx = new Transaction(rvtDoc)) { tx.Start("Load " + targetFamilyName); rvtDoc.LoadFamily(foundFamPath); tx.Commit(); } } // check again for family and type var collector2 = new FilteredElementCollector(rvtDoc).OfClass(targetType); // the optional argument if (targetCategory.HasValue) { collector2.OfCategory(targetCategory.Value); } // Using LINQ query extract for family name and family type var targetElems2 = from element in collector where element.Name.Equals(targetTypeName) && element.get_Parameter(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM).AsString().Equals(targetFamilyName) select element; // put result as list of element for accessing IList <Element> elems2 = targetElems.ToList(); formMsgWPF.Close(); if (elems2.Count > 0) { // Done, exit with the desired element. return(elems2.FirstOrDefault()); } else { SayMsg("Found a family, but it is not right.", "It is either not a " + targetCategory.ToString().Replace("OST_", "") + " or\n" + "it does not having a type:\n" + targetTypeName + "\n\nYou are not standing in tall cotton."); } } else { // At this point no path discovered for the desired Family name. If the desired family // does exist somewhere then have a chance to load it. SayMsg("Item To Place Not Found - Family Load Needed For:", targetCategory.ToString().Replace("OST_", "") + " family:\n" + targetFamilyName + "\n" + "having a type:\n" + targetTypeName + "\n\nMaybe you can find it."); SayMsg("Go Find " + targetFamilyName, "READ ALL OF THIS BEFORE DOING ANYTHING. After closing this message, drag that file anywhere into the Revit Project Browser view." + " Make sure not to drop it on the Properties view. That will open the dragged family in the Family Editor. You will be quite confused." + " That missing family will also not have been added to the project."); }// end fondFamPath formMsgWPF.Close(); return(null); }