/// <summary>
        /// Set new categories, this method will possibly update existing criteria
        /// </summary>
        /// <param name="newCatIds">New categories for current filter.</param>
        /// <returns>true if categories or criteria are changed; otherwise false.</returns>
        /// <remarks>
        /// If someone parameter of criteria cannot be supported by new categories,
        /// the old criteria will be cleaned and set to empty
        /// </remarks>
        public bool SetNewCategories(ICollection <ElementId> newCatIds)
        {
            // do nothing if new categories are equals to old categories
            List <BuiltInCategory> newCats = new List <BuiltInCategory>();

            foreach (ElementId catId in newCatIds)
            {
                newCats.Add((BuiltInCategory)catId.IntegerValue);
            }
            if (ListCompareUtility <BuiltInCategory> .Equals(newCats, m_filterCategories))
            {
                return(false);
            }
            m_filterCategories = newCats; // update categories
            //
            // Check if need to update file rules:
            // . if filer rule is empty, do nothing
            // . if some parameters of rules cannot be supported by new categories, clean all old rules
            ICollection <ElementId> supportParams =
                ParameterFilterUtilities.GetFilterableParametersInCommon(m_doc, newCatIds);

            foreach (FilterRuleBuilder rule in m_filterRules)
            {
                if (!supportParams.Contains(new ElementId(rule.Parameter)))
                {
                    m_filterRules.Clear();
                    break;
                }
            }
            return(true);
        }
        /// <summary>
        /// Update ParameterFilterElement within document with
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void okButton_Click(object sender, EventArgs e)
        {
            // Reserve how many Revit filters need to be updated/removed
            ICollection <String>     updatedFilters = new List <String>();
            ICollection <ElementId>  deleteElemIds  = new List <ElementId>();
            FilteredElementCollector collector      = new FilteredElementCollector(m_doc);
            ICollection <Element>    oldFilters     = collector.OfClass(typeof(ParameterFilterElement)).ToElements();
            //
            // Start transaction to update filters now
            Transaction tran = new Transaction(m_doc, "Update View Filter");

            tran.Start();
            try
            {
                // 1. Update existing filters
                foreach (ParameterFilterElement filter in oldFilters)
                {
                    FilterData filterData;
                    bool       bExist = m_dictFilters.TryGetValue(filter.Name, out filterData);
                    if (!bExist)
                    {
                        deleteElemIds.Add(filter.Id);
                        continue;
                    }
                    //
                    // Update Filter categories and filter rules for this filter
                    ICollection <ElementId> newCatIds = filterData.GetCategoryIds();
                    if (!ListCompareUtility <ElementId> .Equals(filter.GetCategories(), newCatIds))
                    {
                        filter.SetCategories(newCatIds);
                    }
                    IList <FilterRule> newRules = new List <FilterRule>();
                    foreach (FilterRuleBuilder ruleData in filterData.RuleData)
                    {
                        newRules.Add(ruleData.AsFilterRule());
                    }
                    filter.SetRules(newRules);
                    updatedFilters.Add(filter.Name);
                }
                //
                // 2. Delete some filters
                if (deleteElemIds.Count > 0)
                {
                    m_doc.Delete(deleteElemIds);
                }
                //
                // 3. Create new filters(if have)
                foreach (KeyValuePair <String, FilterData> myFilter in m_dictFilters)
                {
                    // If this filter is updated, do nothing
                    if (updatedFilters.Contains(myFilter.Key))
                    {
                        continue;
                    }
                    //
                    // Create new filter now if filter not exist yet
                    IList <FilterRule> rules = new List <FilterRule>();
                    foreach (FilterRuleBuilder ruleData in myFilter.Value.RuleData)
                    {
                        rules.Add(ruleData.AsFilterRule());
                    }
                    ParameterFilterElement.Create(
                        m_doc, myFilter.Key, myFilter.Value.GetCategoryIds(), rules);
                }
                //
                // Commit change now
                tran.Commit();
            }
            catch (Exception ex)
            {
                String failMsg = String.Format("Revit filters update failed and was aborted: " + ex.ToString());
                MyMessageBox(failMsg);
                tran.RollBack();
            }
        }