Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Elegant way to get possible ElementId values for specific Parameter

10 REPLIES 10
SOLVED
Reply
Message 1 of 11
Anonymous
2602 Views, 10 Replies

Elegant way to get possible ElementId values for specific Parameter

Hello,

 

I'm creating a sort of "Property Editor" dialog for user selected elements. In my dialog, the user may pick from a list of non read-only parameters, and specify an alternate value that my application will use later on under particular circumstances (see dialog image below).

 

The challenge is to provide a list of relevant alternate "Element Id Values" based on the selected parameter. So far, my approach is to explicitly exam the "Current Value (ElementId)" of selected parameter and create alternate value list accordingly. For some "Current Values" I use the "GetSimilarTypes" function, while others I simply filter the document for elements of same category (see code below image).

 

So far I have two questions...

 

  1. Can someone suggest a less explicit, more elegant way of populating the alternate ElementId values?
  2. Based on my current approach, if the "Current Value" is NULL, I have no way of getting alternate values.

Thanks,

 

Jon

 

 

 

2017-06-18_18-07-28.jpg

 

 

if (request == EditPropertyOptRequest.GetAvailableValues) {

cond.SelElemValue = null; cond.PropertyOpt.ElementValues = new ObservableCollection<Element>(); try { dynamic CurrentElem = doc.GetElement(cond.SelProperty.AsElementId); if ((CurrentElem) is WallType) { WallType obj = CurrentElem; foreach (void ElemId_loopVariable in obj.GetSimilarTypes) { ElemId = ElemId_loopVariable; cond.PropertyOpt.ElementValues.Add(doc.GetElement(ElemId)); } } else if ((CurrentElem) is FloorType) { FloorType obj = CurrentElem; foreach (void ElemId_loopVariable in obj.GetSimilarTypes) { ElemId = ElemId_loopVariable; cond.PropertyOpt.ElementValues.Add(doc.GetElement(ElemId)); } } else if ((CurrentElem) is FamilySymbol) { FamilySymbol obj = CurrentElem; foreach (void ElemId_loopVariable in obj.GetSimilarTypes) { ElemId = ElemId_loopVariable; cond.PropertyOpt.ElementValues.Add(doc.GetElement(ElemId)); } } else if ((CurrentElem) is Level) { FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Levels).WhereElementIsNotElementType(); foreach (void elem_loopVariable in collector) { elem = elem_loopVariable; cond.PropertyOpt.ElementValues.Add(elem); } } else if ((CurrentElem) is Phase) { FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Phases).WhereElementIsNotElementType(); foreach (void elem_loopVariable in collector) { elem = elem_loopVariable; cond.PropertyOpt.ElementValues.Add(elem); } } cond.SelElemValue = cond.PropertyOpt.ElementValues(0); } catch (Exception ex) { } }

 

10 REPLIES 10
Message 2 of 11
Anonymous
in reply to: Anonymous

Quick update...

 

After realizing "GetSimilarTypes" method is inherited from "ElementType" base class, I now attempt to cast Element to ElementType, then use "GetSimilarTypes" method if "ElemType" is Not NULL. Otherwise I filter document for NonElementTypes of same Category. I still need to handle elements with No Category, which so far I've identified Line Styles as being this way.

 

I am quite happy with this approach!

 

Jon 

 

if (request == EditPropertyOptRequest.GetAvailableValues) {
	cond.SelElemValue = null;
	cond.PropertyOpt.ElementValues = new ObservableCollection<Element>();

	if (cond.SelProperty.StorageType == StorageType.ElementId) {
		ElementId ElemId = cond.SelProperty.AsElementId;
		if (ElemId == null)
			return;

		Element Elem = doc.GetElement(ElemId);
		ElementType ElemType = Elem as ElementType;

		if (ElemType != null) {
			foreach ( ElemId in ElemType.GetSimilarTypes) {
				cond.PropertyOpt.ElementValues.Add(doc.GetElement(ElemId));
			}

		} else if (Elem.Category != null) {
			FilteredElementCollector collector = new FilteredElementCollector(doc);
			collector.OfCategory(Elem.Category.Id.IntegerValue).WhereElementIsNotElementType();

			foreach ( Elem in collector) {
				cond.PropertyOpt.ElementValues.Add(Elem);
			}
		} else {
			//
			//Handle non-category elements. Namely Line Styles(aka GraphicStlyes)
			//
		}

		cond.SelElemValue = cond.PropertyOpt.ElementValues(0);

	}

}

 

Message 3 of 11
jeremytammik
in reply to: Anonymous

Dear Jon,

 

Thank you for sharing this.

 

How does this fit in with the combo box dropdown workarounds suggested here?

 

http://thebuildingcoder.typepad.com/blog/2015/11/drop-down-enumerated-parameter-values.html

 

Should I add your solution as a new workaround, or is it a different class of animal?

 

Thank you!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 4 of 11
Anonymous
in reply to: jeremytammik

Hi Jeremy,

 

I believe this is a "different class of animal". In brief, the post touches on how to mimic contextual content of Element Properties Panel using Revit API. More specifically, how to get a list of available ElementId values for a given Parameter whos Storage Type = ElementId and has an existing value to use as reference. Mostly revolving around use of 'ElementType.GetSimilarTypes' method.

 

Note: I still cant find a way to get available values for a Parameter that does not have existing value for reference.

 

Thanks,

 

Jon

 

 

Message 5 of 11
jeremytammik
in reply to: Anonymous

Dear Jon,

 

Thank you, all clear now.

 

To get available values for a Parameter that does not have an existing value for reference, you might be able to create a suitable template element in a temporary transaction, grab the data you require from it, and roll back the transaction without committing, also know as the 'temporary transaction trick' TTT:

 

http://thebuildingcoder.typepad.com/blog/about-the-author.html#5.53

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 6 of 11
Anonymous
in reply to: jeremytammik

Thanks for suggestion Jeremy,

 

TTT may work, but I don't see a way to determine what a "suitable template element" might be. Given a parameter with <null> ElementID value, the only helpful information looks like BuiltInParameter Id, but that doesn't get me very far. Worst case, I make exceptions for my favorite BuiltInParameter Id's to assist in determining "suitable template element".

 

Almost as if the Parameter class would benefit from something like a "GetSampleValueType" method.

 

Jon

 

 

Message 7 of 11
FAIR59
in reply to: Anonymous

you can use a ElementParameterFilter, to get all the elements that have a value other then ElementId.InvalidElementId  for a specific parameter.

 

this code filters for elements in the active view, that are demolished in some phase.

 

            ParameterValueProvider pvp_Demolished = new ParameterValueProvider(new ElementId((int)BuiltInParameter.PHASE_DEMOLISHED));
            FilterNumericGreater fgreater = new FilterNumericGreater();
            FilterElementIdRule IdFilter = new FilterElementIdRule(pvp_Demolished, fgreater, ElementId.InvalidElementId);
            ElementParameterFilter efilter = new ElementParameterFilter(IdFilter);

            FilteredElementCollector elems = new FilteredElementCollector(doc, doc.ActiveView.Id)
                .WherePasses(efilter);

 

 

Message 8 of 11
Anonymous
in reply to: FAIR59

Thanks for the suggestion FAIR59,

 

Unfortunately that's not what I'm looking to accomplish. Please see video below for better explanation of what I'm trying to do. Maybe you might have another idea.

 

Thanks,

 

Jon

 

Message 9 of 11
FAIR59
in reply to: Anonymous

Actually, it is part of what you are trying to accomplish. With an ElementParameterFilter you get a list of Elements (if there are any) that have a value for the parameter in question, and then you may find all the relevant values, or display all the found values.  

Message 10 of 11
Anonymous
in reply to: FAIR59

Oh I see now, VERY CLEVER!!!

 

Just implemented and works like a charm. Only caveat like you say is "if there are any", but I can live with that.

 

Thanks for the great tip!!!

 

Jon

 

 

 

 

Message 11 of 11
jeremytammik
in reply to: Anonymous

Rescued for posterity here:

 

http://thebuildingcoder.typepad.com/blog/2017/06/finding-an-exit-path-and-elementid-parameter-values...

 

Thanks guys, especially Fair59!

 

Cheers,

 

Jeremy



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


Autodesk Design & Make Report