Access and update instance parameter of a newly placed family instance

Access and update instance parameter of a newly placed family instance

Guri009
Participant Participant
709 Views
6 Replies
Message 1 of 7

Access and update instance parameter of a newly placed family instance

Guri009
Participant
Participant

Hi Everyone,

 

I am looking to access a specific instance parameter of a family instance placed with a custom C# command. Below is the code that loads the family and then places it as a family symbol.

 

private static FamilySymbol LoadFamilySymbol(string path, string famName)
{
FamilySymbol famSymbol = null;
Family fam = null;


WsprFamilyLoadOptions loadOptions = new WsprFamilyLoadOptions();

Transaction t = new Transaction(ndoc, "T1");
t.Start();

ndoc.LoadFamilySymbol(path, famName, (IFamilyLoadOptions)(object)loadOptions, out famSymbol);

famSymbol.Activate();

t.Commit();
return famSymbol;
}

 

public static FamilySymbol FamilySymbolPlacement(Document doc, UIDocument uidoc, string FamilyName, byte[] Family)
{
    String path = string.Format("C:\\temp\\{0}.rfa", FamilyName);

    File.WriteAllBytes(path, Family);

    FamilySymbol familySymbol = null;

    try
    {
        familySymbol = LoadFamilies.LoadFamilySymbol(path, FamilyName);

        PromptForFamilyInstancePlacementOptions famoptions = null;

        if (familySymbol != null)
        {
            try
            {
                if (famoptions == null)
                {
                    uidoc.PromptForFamilyInstancePlacement(familySymbol);
                }
                else
                {
                    uidoc.PromptForFamilyInstancePlacement(familySymbol, famoptions);
                }
            }
            catch (RvtExceptions.OperationCanceledException val)
            {
                ProjectData.SetProjectError((Exception)val);
                RvtExceptions.OperationCanceledException ex3 = val;
                ProjectData.ClearProjectError();
            }
        }
    }
    catch (RvtExceptions.InvalidOperationException val2)
    {
        ProjectData.SetProjectError((Exception)val2);
        RvtExceptions.InvalidOperationException ex2 = val2;
        ProjectData.ClearProjectError();
    }
    return familySymbol;

 

Below are a few way I have tried to access the instance parameter of the family symbol.

1.

FamilySymbol fsym = PlaceFamilies.PlaceFamilySymbol(FamilyNames.BreakLine_Normal, Resources.Break_Line_Normal, uidoc, doc);

Element e = fsym;

Parameter test = e.ParametersMap.get_Item("Drawing Scale");

2.

Parameter param2 = e.LookupParameter("Drawing Scale");

3. 

Element e = fsym;
foreach(Parameter p in e.ParametersMap)
{
Debug.Print(p.Definition.Name);
string s = p.Definition.Name;
}

 

I have been unable to access instance parameter "Drawing Scale" with any of the above methods.

Upon checking with Revit Lookup, Element e in above code returns the id of the family instead of family instance, how can I access the family instance?

 

Just to clarify it further, the newly placed family instance does have parameter "Drawing Scale" in the properties panel.

Found the below link for setting parameter values but this used FamilyManager which can only run in a Family document, my command is meant to run in the project document.
https://thebuildingcoder.typepad.com/blog/2011/11/set-family-parameter-requires-type.html 

 

Checked below post on the forum which highlights that a transaction needs to be started for placement and parameters to be accessed within the transaction, but PromptForFamilyInstancePlacement starts its own transaction and does not allow to be run within another transaction.

 

Would be great if anyone is able to provide any guidance towards accessing and modifying the instance parameter of the family symbol.

 

Thank you

0 Likes
Accepted solutions (1)
710 Views
6 Replies
Replies (6)
Message 2 of 7

scgq425
Advocate
Advocate

Hi @Guri009 :

in u code , the fsym , if u want get the instance access parameter , u need to get the instance not symbol  , if u use the uidoc.PromptForFamilyInstancePlacement() , u can add a event : documentchaned to monitor which instance is add newest ,and then get the target paramater 'drawing scale' . 

LanHui Xu 徐兰辉
Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.

Blog
LinkedIn
Revit/CAD Development | Steel Product Manager

EESignature

0 Likes
Message 3 of 7

Mohamed_Arshad
Advisor
Advisor

HI @Guri009 

 

    I read you complete issue. I can't see such parameter you're trying to access, So can you send a snip image of "Drawing Scale" Parameter from Revit UI or Revit Lookup UI, So that I can help out 


Mohamed Arshad K
Software Developer (CAD & BIM)

0 Likes
Message 4 of 7

Guri009
Participant
Participant

Hi @Mohamed_Arshad 

 

Please see image below from Revit Lookup and "Drawing Scale" parameter shown in the Revit properties window as well.

Guri009_0-1711100200568.png

 

0 Likes
Message 5 of 7

Mohamed_Arshad
Advisor
Advisor
Accepted solution

Hi @Guri009 

We have two Methods for accessing the FamilyInstance Parameters.

 

Method-01 (Standard Method)

 

Revit Workflow for Family Placement and Parameter Accessing

1. Load Family.

2. Get FamilySymbol from Loaded Family.

3. Place the FamilySymbol into the Project using NewFamilyInstance Method.

4. Access the Parameter of the FamilyInstance using LookupParameter Method.

 

You need to replace with NewFamilyInstance Method.

 

uidoc.PromptForFamilyInstancePlacement(familySymbol);

 

 

Kindly check the below code for additional reference

 

Document doc = commandData.Application.ActiveUIDocument.Document;

                //Load the Family from the folder and get Family as out parameter
                doc.LoadFamily("C:\\temp\\{0}.rfa", out Family family);

                ///Get Family Symmbol from the Family (I'm taking First Family)
                FamilySymbol sym = doc.GetElement(family.GetFamilySymbolIds().First()) as FamilySymbol;

                using (Transaction placeFamily = new Transaction(doc, "Place Family"))
                {
                    placeFamily.Start();

                    if (!sym.IsActive)
                    {
                        sym.Activate();
                    }

                    ///Place Family to Sheet (I'm Placing Family in 0,0,0 Posiion, you can change the position)
                    FamilyInstance inst = doc.Create.NewFamilyInstance(XYZ.Zero, sym, doc.ActiveView);

                    ///Access Parameter (Give Value in Feet) (My Input is in mm so i used 304.8 to convert mm to feet)
                    inst.LookupParameter("Drawing Scale").Set(30 / 304.8);

                    placeFamily.Commit();
                }

 

 

Method-02 (Little Modification in you existing Code)

 

Or if you don't want to remove then you need to add FilteredElementCollector Class (Filter) and filter the placed instance. Then Access the Parameters. Kindly check the Blow code for additional reference.

 

uidoc.PromptForFamilyInstancePlacement(familySymbol);​

 

 

Method-02 Additional Reference Code

 

/// (I'm taking First Family Instnace placed on the view)
                FamilyInstance instance = new FilteredElementCollector(doc, doc.ActiveView.Id)
                    .OfClass(typeof(FamilyInstance))
                    .OfCategory(BuiltInCategory.OST_DetailComponents)
                    .Where(x => x.Name == "Breakline Normal")
                    .First() as FamilyInstance;

                using (Transaction editParameter= new Transaction(doc,"Edit Parameter"))
                {
                    editParameter.Start();

                    instance.LookupParameter("Drawing Scale").Set(30 / 304.8);

                    editParameter.Commit();
                }

 

 

 Hope this will Helps 🙂

 


Mohamed Arshad K
Software Developer (CAD & BIM)

0 Likes
Message 6 of 7

Guri009
Participant
Participant

Hi @Mohamed_Arshad 

 

Thank you for your help, your second option helped me to filter out the family instances, did it a bit differently since I needed all the instances not just the first one. Below for your reference and if you have any comments.

 

            double viewScale = doc.ActiveView.Scale;

            FilteredElementCollector collector = new FilteredElementCollector(doc);
            collector = collector.OfClass(typeof(FamilySymbol)).OfCategory(BuiltInCategory.OST_DetailComponents);

            var query = from Element in collector where Element.Name == FamilyNames.BreakLine_Normal select Element;
            List<Element> famSyms = query.ToList<Element>();
            ElementId symId = famSyms[0].Id;

            FamilyInstanceFilter instanceFilter = new FamilyInstanceFilter(doc, symId);

            collector = new FilteredElementCollector(doc, doc.ActiveView.Id);
            ICollection<Element> famInstances = collector.WherePasses(instanceFilter).ToElements();

            List<Element> elemList = new List<Element>();

            if (famInstances.Count > 0)
            {
                elemList.AddRange(famInstances);
            }
            foreach (Element elem in elemList)
            {
                ElementId eId = elem.Id;
                using (Transaction param = new Transaction(doc, "Update Paramters"))
                {
                    param.Start();
                    Parameter scale = elem.LookupParameter("Drawing Scale");
                    scale.Set(viewScale);
                    param.Commit();
                }
            }
0 Likes
Message 7 of 7

Guri009
Participant
Participant

Hi @scgq425 

 

Thank you for your suggestion, I haven't used events before, but I am curious to investigate the use of document changed event for this because as a next step I would like to update the parameter when the view scale changes.

0 Likes