/// <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);
        }
Exemplo n.º 3
0
        /// <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);
            }
        }