ParameterFilterElement doesn't accept shared parameters?

ParameterFilterElement doesn't accept shared parameters?

dean.hayton
Participant Participant
1,053 Views
7 Replies
Message 1 of 8

ParameterFilterElement doesn't accept shared parameters?

dean.hayton
Participant
Participant

Hi All,

 

I have some code to collect a view filter from a Revit active view from which I create an element filter using .GetElementFilter() for use in a FilteredElementCollector to collect walls from a linked model. This process has worked fine in one project using a built in parameter in the view filter, but when trying to use it with a shared parameter it returns no results. I have checked the shared parameter exists in both my model and the link model but I have noticed that if I snoop the shared parameter from a linked wall, It's id is different from the one returned from .GetElementFilterParameter(). Is the issue as simple as I can't use a shared parameter in a ParameterFilterElement?

 

Thanks

Accepted solutions (1)
1,054 Views
7 Replies
Replies (7)
Message 2 of 8

WillianMayrink
Participant
Participant

I don't know if I understood very well, but using shared parameter guid you can get shared parameter and create a ParameterFilterElement, like this:

var guidSharedParameter = new Guid("xxxxxx");
var sharedParamId = SharedParameterElement.Lookup(doc, uidSharedParameter).Id;
var paramValueProvider = new ParameterValueProvider(sharedParamId);
var rule = new FilterStringRule(paramValueProvider, new FilterStringEquals(),"valueString", false);
var elementFilter = new ElementParameterFilter(rule);
var paramFilter = ParameterFilterElement.Create(doc, "filterName", new List<ElementId>() { new ElementId(BuiltInCategory.OST_GenericModel) });
paramFilter.SetElementFilter(elementFilter);

 

0 Likes
Message 3 of 8

RPTHOMAS108
Mentor
Mentor

The best way to collect elements from a linked model is to create the FilteredElementCollector using the linked document.

 

The ElementId for the BIP would be the same in both models since it is based on the BIP enum values. The shared parameter has a ParameterElement created in each model and those would have different ElementIds.

 

Are you saying that you are able to filter for linked elements in a view of a host document that the FilteredElementCollector was established for? I'm not sure how that would work since some of the ElementIds would clash across the two documents i.e. if you were returning ElementIds from the collector how would you know the document origin of them? ElementId is completely ignorant of the document the element it represents comes from.

0 Likes
Message 4 of 8

dean.hayton
Participant
Participant

@WillianMayrink @RPTHOMAS108 thanks for the replies. I think I'm getting my wires crossed a bit so I'll try to explain again. The goal is to collect walls (and other elements but we'll say walls for now) from a linked model and copy/paste them into my document (I don't want to use copy/monitor). To specify which walls to copy, I use a view filter to look for say all walls with FRR in their type name. Using python and Dynamo I can then get this view filter and use viewfilter.GetElementFilter() to create an element filter that I can pass into the filtered element collector to collect the walls. This works if the view filter is looking for a built in parameter like type name, mark, etc. but it seems it doesn't work for shared parameters. Here is a snippet of code below:

view_filters = active_view.GetOrderedFilters()
found_filter = match_viewfilter_to_name(view_filter_name, view_filters)#returns the view filter matching a user specified selection
view_filter_filter = found_filter.GetElementFilter()#filter to apply to collector
view_filter_categories = found_filter.GetCategories()#categories for collector
	
cat_list = List[ElementId]()
for cat in view_filter_categories:
	cat_list.Add(cat)
		
multi_cat_filter = ElementMulticategoryFilter(cat_list)
	
for link_inst in link_insts:
	
    link_doc = link_inst.GetLinkDocument()
    elements = FilteredElementCollector(link_doc).WherePasses(multi_cat_filter).WherePasses(view_filter_filter).ToElements()
0 Likes
Message 5 of 8

RPTHOMAS108
Mentor
Mentor
Accepted solution

It is likely as you state the ElementId for the SharedParameterElement will be different according to the link document it is in (so will be meaningless if you try to use the same ElementId in a different document). For each link document you can use SharedParameterElement.Lookup(Document, GUID) then provide the common GUID to get the correct ElementId for use in the filter of that document but you would have to recreate the affected FilterElements. 

 

It is probably easier to try creating a view template from the view and copy that to the linked model via ElementTransformUtils. Often when you copy views dependant elements such as filters would also be copied. 

 

The built-in parameters I suspect are not affected since they use a common ElementId throughout documents i.e. the value from the built-in parameter enum.

 

 

0 Likes
Message 6 of 8

dean.hayton
Participant
Participant

Seems like I'm going to have to change my approach for this. Thank you for the help

0 Likes
Message 7 of 8

havard.leding
Contributor
Contributor

Having the same issue.

The strange thing is that the ViewFilter (ParameterFilterElement) works fine in the UI.
Based on a shared parameter it will color both linked walls and non-linked walls.
Even though the parameter ElementId is different in the two documents.

 

So in the UI both SharedParameters and BuiltInParameters work.

But using the exact same ParameterFilterElement with a FilteredElementCollector it only works with BuiltInParameters.

 

The long way around is maybe to reconstruct a new ParameterFilterElement  from the "old" - with the "correct" ElementId from the linked document. But it doesnt seem trivial to figure out if a FilterRule is a "BeginsWithRule" or "ContainsRule" ++

 

I might create a minimum sample VS solution for this once im finished digging into it.

 

 

 

 

 

 

0 Likes
Message 8 of 8

havard.leding
Contributor
Contributor

This could be a workaround,

Substituting the host SharedParameter.Id with the linked SharedParameter.Id.
Not tested this code at all its 2am now but it should work... i think 🙂 

Im still curious why it works in the UI and not in the API.

If it still doesnt work in V2024 it should perhaps be raised as an issue.

Adapted from this page:
https://boostyourbim.wordpress.com/2016/05/11/filter-rule-data-where-is-it-hiding/

 

var rule = rules.First();
                                FilterRule newRule = null;
                                SharedParameterElement spe = HostDoc.GetElement(rule.GetRuleParameter()) as SharedParameterElement;
                                SharedParameterElement speInLink = SharedParameterElement.Lookup(LinkDoc, spe.GuidValue);
                                if (rule is FilterDoubleRule fdr)
                                {
                                    ParameterValueProvider provider = new ParameterValueProvider(speInLink.Id);
                                    newRule = new FilterDoubleRule(provider, fdr.GetEvaluator(), fdr.RuleValue, fdr.Epsilon);
                                }
                                else if (rule is FilterStringRule fsr)
                                {
                                    ParameterValueProvider provider = new ParameterValueProvider(speInLink.Id);
                                    newRule = new FilterStringRule(provider, fsr.GetEvaluator(), fsr.RuleString);
                                }
                                else if (rule is FilterIntegerRule fir)
                                {
                                    ParameterValueProvider provider = new ParameterValueProvider(speInLink.Id);
                                    newRule = new FilterIntegerRule(provider, fir.GetEvaluator(), fir.RuleValue);
                                }
                                else if (rule is FilterElementIdRule fidr)
                                {
                                    ParameterValueProvider provider = new ParameterValueProvider(speInLink.Id);
                                    newRule = new FilterElementIdRule(provider, fidr.GetEvaluator(), fidr.RuleValue);
                                }

 

0 Likes