/// <summary> /// This method takes a category and information /// about a project parameter and adds a binding /// to the category for the parameter. It will /// throw an exception if the parameter is already /// bound to the desired category. It returns /// whether or not the API reports that it /// successfully bound the parameter to the /// desired category. /// </summary> /// <param name="doc">The project document in which the project parameter has been defined</param> /// <param name="projectParameterData">Information about the project parameter</param> /// <param name="category">The additional category to which to bind the project parameter</param> /// <returns></returns> static bool AddProjectParameterBinding( Document doc, ProjectParameterData projectParameterData, Category category) { // Following good SOA practices, first validate incoming parameters if (doc == null) { throw new ArgumentNullException("doc"); } if (doc.IsFamilyDocument) { throw new Exception( "doc can not be a family document."); } if (projectParameterData == null) { throw new ArgumentNullException( "projectParameterData"); } if (category == null) { throw new ArgumentNullException("category"); } bool result = false; CategorySet cats = projectParameterData.Binding .Categories; if (cats.Contains(category)) { // It's already bound to the desired category. // Nothing to do. string errorMessage = string.Format( "The project parameter '{0}' is already bound to the '{1}' category.", projectParameterData.Definition.Name, category.Name); throw new Exception(errorMessage); } cats.Insert(category); // See if the parameter is an instance or type parameter. InstanceBinding instanceBinding = projectParameterData.Binding as InstanceBinding; if (instanceBinding != null) { // Is an Instance parameter InstanceBinding newInstanceBinding = doc.Application.Create .NewInstanceBinding(cats); if (doc.ParameterBindings.ReInsert( projectParameterData.Definition, newInstanceBinding)) { result = true; } } else { // Is a type parameter TypeBinding typeBinding = doc.Application.Create .NewTypeBinding(cats); if (doc.ParameterBindings.ReInsert( projectParameterData.Definition, typeBinding)) { result = true; } } return(result); }
} // end of PopulateProjectParameterData #endregion // Private helper methods public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Document doc = uidoc.Document; if (doc.IsFamilyDocument) { message = "The document must be a project document."; return(Result.Failed); } // Get the (singleton) element that is the // ProjectInformation object. It can only have // instance parameters bound to it, and it is // always guaranteed to exist. Element projectInfoElement = new FilteredElementCollector(doc) .OfCategory(BuiltInCategory.OST_ProjectInformation) .FirstElement(); // Get the first wall type element. It can only // have type parameters bound to it, and there is // always guaranteed to be at least one of these. Element firstWallTypeElement = new FilteredElementCollector(doc) .OfCategory(BuiltInCategory.OST_Walls) .WhereElementIsElementType() .FirstElement(); CategorySet categories = null; Parameter foundParameter = null; // Get the list of information about all project // parameters, calling our helper method, below. List <ProjectParameterData> projectParametersData = GetProjectParameterData(doc); // In order to be able to query whether or not a // project parameter is shared or not, and if it // is shared then what it's GUID is, we must ensure // it exists in the Parameters collection of an // element. // This is because we cannot query this information // directly from the project parameter bindings // object. // So each project parameter will attempt to be // temporarily bound to a known object so a // Parameter object created from it will exist // and can be queried for this additional // information. foreach (ProjectParameterData projectParameterData in projectParametersData) { if (projectParameterData.Definition != null) { categories = projectParameterData.Binding.Categories; if (!categories.Contains(projectInfoElement.Category)) { // This project parameter is not already // bound to the ProjectInformation category, // so we must temporarily bind it so we can // query that object for it. using (Transaction tempTransaction = new Transaction(doc)) { tempTransaction.Start("Temporary"); // Try to bind the project parameter do // the project information category, // calling our helper method, below. if (AddProjectParameterBinding( doc, projectParameterData, projectInfoElement.Category)) { // successfully bound foundParameter = projectInfoElement.get_Parameter( projectParameterData.Definition); if (foundParameter == null) { // Must be a shared type parameter, // which the API reports that it binds // to the project information category // via the API, but doesn't ACTUALLY // bind to the project information // category. (Sheesh!) // So we must use a different, type // based object known to exist, and // try again. if (!categories.Contains( firstWallTypeElement.Category)) { // Add it to walls category as we // did with project info for the // others, calling our helper // method, below. if (AddProjectParameterBinding( doc, projectParameterData, firstWallTypeElement.Category)) { // Successfully bound foundParameter = firstWallTypeElement.get_Parameter( projectParameterData.Definition); } } else { // The project parameter was already // bound to the Walls category. foundParameter = firstWallTypeElement.get_Parameter( projectParameterData.Definition); } if (foundParameter != null) { PopulateProjectParameterData( foundParameter, projectParameterData); } else { // Wouldn't bind to the walls // category or wasn't found when // already bound. // This should probably never happen? projectParameterData.IsSharedStatusKnown = false; // Throw exception? } } else { // Found the correct parameter // instance on the Project // Information object, so use it. PopulateProjectParameterData( foundParameter, projectParameterData); } } else { // The API reports it couldn't bind // the parameter to the ProjectInformation // category. // This only happens with non-shared // Project parameters, which have no // GUID anyway. projectParameterData.IsShared = false; projectParameterData.IsSharedStatusKnown = true; } tempTransaction.RollBack(); } } else { // The project parameter was already bound // to the Project Information category. foundParameter = projectInfoElement.get_Parameter( projectParameterData.Definition); if (foundParameter != null) { PopulateProjectParameterData( foundParameter, projectParameterData); } else { // This will probably never happen. projectParameterData.IsSharedStatusKnown = false; // Throw exception? } } } // Whether or not the Definition object could be found } // For each original project parameter definition StringBuilder sb = new StringBuilder(); // Build column headers sb.AppendLine("PARAMETER NAME\tIS SHARED?\tGUID"); // Add each row. foreach (ProjectParameterData projectParameterData in projectParametersData) { sb.Append(projectParameterData.Name); sb.Append("\t"); if (projectParameterData.IsSharedStatusKnown) { sb.Append(projectParameterData.IsShared.ToString()); } else { sb.Append("<Unknown>"); } if (projectParameterData.IsSharedStatusKnown && projectParameterData.IsShared) { sb.Append("\t"); sb.Append(projectParameterData.GUID); } sb.AppendLine(); } System.Windows.Clipboard.Clear(); System.Windows.Clipboard.SetText(sb.ToString()); TaskDialog resultsDialog = new TaskDialog( "Results are in the Clipboard"); resultsDialog.MainInstruction = "Results are in the Clipboard"; resultsDialog.MainContent = "Paste the clipboard into a spreadsheet " + "program to see the results."; resultsDialog.Show(); return(Result.Succeeded); }
/// <summary> /// 将外部共享参数创建为项目参数,并将其绑定到指定的类别 /// </summary> /// <param name="transDoc"> bindingMap.Insert 与 bindingMap.ReInsert 方法必须在事务内才能执行</param> /// <param name="doc"></param> /// <param name="facenCategoryId"> 面层对象所属的类别 </param> public void BindParametersToCategory(Transaction transDoc, Document doc, ElementId facenCategoryId) { // 打开共享文件 Autodesk.Revit.ApplicationServices.Application app = doc.Application; string OriginalSharedFileName = app.SharedParametersFilename; // Revit程序中,原来的共享文件路径 app.SharedParametersFilename = ProjectPath.SharedParameters; // 设置Revit的共享参数文件 DefinitionFile myDefinitionFile = app.OpenSharedParameterFile(); // 如果没有找到对应的文件,则打开时不会报错,而是直接返回Nothing // app.SharedParametersFilename = OriginalSharedFileName; // 将Revit程序中的共享文件路径还原,以隐藏插件程序中的共享参数文件。 // create a new group in the shared parameters file DefinitionGroup myGroup = myDefinitionFile.Groups.get_Item(FaceWallParameters.sp_Group_Face); // 提取此共享参数组中的每一个参数,并赋值给指定的类别 ExternalDefinition exdef_FaceIdTag = (ExternalDefinition)myGroup.Definitions.get_Item(FaceWallParameters.sp_FaceIdTag); ExternalDefinition exdef_FaceType = (ExternalDefinition)myGroup.Definitions.get_Item(FaceWallParameters.sp_FaceType); ExternalDefinition exdef_Volumn = (ExternalDefinition)myGroup.Definitions.get_Item(FaceWallParameters.sp_Volumn); ExternalDefinition exdef_Area = (ExternalDefinition)myGroup.Definitions.get_Item(FaceWallParameters.sp_Area); // BindingMap bindingMap = doc.ParameterBindings; Category myCategory = Category.GetCategory(doc, facenCategoryId); // --------------------------------------------------------------------------------------------------------- // 判断指定的类别中是否绑定有此 "面层标识 FaceIdTag" 参数 bool faceParaHasInsertedIntoThatCategory = false; bool parameterHasBeenAddedToProject = false; if (bindingMap.Contains(exdef_FaceIdTag)) { Autodesk.Revit.DB.Binding parameterBinding = doc.ParameterBindings.get_Item(exdef_FaceIdTag); parameterHasBeenAddedToProject = true; if (parameterBinding is InstanceBinding) { // 外部共享参数 exdef_FaceIdTag 在此文档中 绑定到了哪些类别 CategorySet bindedCategories = ((InstanceBinding)parameterBinding).Categories; if (bindedCategories.Contains(myCategory)) { faceParaHasInsertedIntoThatCategory = true; } } } // --------------------------------------------------------------------------------------------------------- // 如果此参数"面层标识 FaceIdTag"还没有被添加到项目参数中,则先将用 Insert 其进行添加 if (!parameterHasBeenAddedToProject) { // 在“项目参数”中添加此参数,并为其指定一个绑定的类别。 CategorySet myCategories = app.Create.NewCategorySet(); myCategories.Insert(myCategory); //Create an instance of InstanceBinding InstanceBinding instanceBinding = app.Create.NewInstanceBinding(myCategories); // Get the BingdingMap of current document. // Bind the definitions to the document bindingMap.Insert(exdef_FaceIdTag, instanceBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); // 此 Insert 操作必须在事务开启后才能执行 bindingMap.Insert(exdef_FaceType, instanceBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); bindingMap.Insert(exdef_Volumn, instanceBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); bindingMap.Insert(exdef_Area, instanceBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); } // --------------------------------------------------------------------------------------------------------- // 如果"面层标识 FaceIdTag" 参数已经绑定到了指定的类别上,就认为其他三个参数也绑定上来了,此时就不需要再绑定了; // 如果没有绑定,则要将这四个参数一次性全部绑定到此指定的类别上 if (parameterHasBeenAddedToProject && !faceParaHasInsertedIntoThatCategory) { Autodesk.Revit.DB.Binding parameterBinding = doc.ParameterBindings.get_Item(exdef_FaceIdTag); ((InstanceBinding)parameterBinding).Categories.Insert(myCategory); // 将新的类别添加到 binding 的类别集合中 // 重新进行绑定 bindingMap.ReInsert(exdef_FaceIdTag, parameterBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); bindingMap.ReInsert(exdef_FaceType, parameterBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); bindingMap.ReInsert(exdef_Volumn, parameterBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); bindingMap.ReInsert(exdef_Area, parameterBinding, BuiltInParameterGroup.PG_IDENTITY_DATA); } }