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: 

Associate a family parameter

15 REPLIES 15
SOLVED
Reply
Message 1 of 16
GeomGym
4031 Views, 15 Replies

Associate a family parameter

Hi,

 

I'm trying to associate the material parameter on an extrusion with a family parameter.

 

Open a new structural column family (I used the out of the box Metric Structural Column.rft) and run the attached code.

A document regeneration exception is thrown.  I can manually associate the parameter after.

 

Any advice appreciated.

 

Cheers,

 

Jon

15 REPLIES 15
Message 2 of 16
GeomGym
in reply to: GeomGym

I assume this is a bug in Revit???

 

If I haven't explained clearly, please let me know and I will clarify.

 

Thanks,

 

Jon

Message 3 of 16
Aaron.Lu
in reply to: GeomGym

Dear, I've created an issue, REVIT-79279 - API: AssociateElementParameterToFamilyParameter throws InvalidOperationException

it should be a defect. Thanks for reporting!


Aaron Lu
Developer Technical Services
Autodesk Developer Network
Message 4 of 16
Aaron.Lu
in reply to: GeomGym

Hi Geom, we've found a workaround:
before associate the parameter, just set some default family to it:

FamilyType famType = doc.FamilyManager.CurrentType;
if (famType != null & !famType.HasValue(familyParameter))
{ doc.FamilyManager.Set(familyParameter,prm.AsElementId()); }


Aaron Lu
Developer Technical Services
Autodesk Developer Network
Message 5 of 16
Anonymous
in reply to: Aaron.Lu

This is working now in Revit 2016:

 

private static bool SetFamilyMaterial(Document famdoc, Sweep geo, ElementId mId)
{
   if (geo.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM) != null)
   {
      Parameter param = geo.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM);
      if (param.Set(mId))
      {
         FamilyParameter famparam = famdoc.FamilyManager.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);

         if (famparam != null && famdoc.FamilyManager.CanElementParameterBeAssociated(param))
         {
            try
            {
               famdoc.FamilyManager.Set(famparam, param.AsElementId());
               famdoc.FamilyManager.AssociateElementParameterToFamilyParameter(param, famparam);
               return true;
            }
            catch (Exception ex1)
            {
               MessageBox.Show(ex1.ToString());
               return false;
            }
        }
        else
        {
           return false;
        }
    }
    else
    {
        return false;
    }
}
else
{
    return false;
}
}

Message 6 of 16
dirk.neethling
in reply to: Anonymous

Hello chhadi,

 

your solution looks interesting. I just want to be able to change my Material type either within a Family document upon creation, or once the FamilyInstance is available, whichever is possible. Sounds trivial, but seems to be an epic in Revit.

In your method, what is "ElementId mId"?

dirk

Message 7 of 16
Anonymous
in reply to: dirk.neethling

Hi Dirk,

 

I am creating the material on the outside and just passing the id into this function. The material live in the document and I have a script that creates all our needed families. 

 

regards

Christian

 

PS: Everything in Revit is an epic approach. 😉

Message 8 of 16
dirk.neethling
in reply to: Anonymous

Hello CHristian,

 

thanks for your quick Response. One more question:

 

I am adding a FamilyParameter for "Material" to the Family I generate, using the following code:

 

FamilyParameter familyParameter

= familyMgr.AddParameter("Material", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, true);

 

When I run your Method using the ElementId of the Material, I get 

 

famparam == null

 

at the following Point:

 

FamilyParameter famparam = famdoc.FamilyManager.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);

 

So the "Material" FamilyParameter I added before is not recognised. How can I get it to be recognised?

Greetings, DIrk

Message 9 of 16
Anonymous
in reply to: dirk.neethling

Hi Dirk,

 

I dont understand. Why do you need to make a new material parameter. This thing should already be there. Do you have Revit lookup installed? Helps a lot in finding out what parameters are in the document or on the element.

 

I never create a new material parameter, but do create a new material and assign it to the existing parameter.

 

public static List<ElementId> Set(Document doc, Document famdoc, FamilyEntry f)
{
    List<ElementId> mIds = new List<ElementId>();
    Material m1 = Materials.GetMaterials(doc, f.Material1.Name);
            
    ElementId mId1, mId2;

    if (m1 != null)
    {
        using (Transaction trans = new Transaction(famdoc, "Change Material Color"))
        {
            try
            {
                trans.Start();
                        
                mId1 = Material.Create(famdoc, f.Material1.Name);

                if (mId1 != null)
                {
                    Material mat1 = famdoc.GetElement(mId1) as Material;
                    AppearanceAssetElement asset1 = doc.GetElement(m1.AppearanceAssetId) as AppearanceAssetElement;
                    AppearanceAssetElement asset2 = AppearanceAssetElement.Create(famdoc, f.Material1.Name, asset1.GetRenderingAsset());

                    FilteredElementCollector coll = new FilteredElementCollector(famdoc).OfClass(typeof(FillPatternElement));
                    FillPatternElement pattern = null;
                    if (f.Material1.Name == "your material name1")
                    {
                        pattern = coll.FirstOrDefault<Element>(e => e.Name.Equals("Steel")) as FillPatternElement;
                    }
                    else if (f.Material1.Name == "your material name2")
                    {
                        pattern = coll.FirstOrDefault<Element>(e => e.Name.Equals("Solid fill")) as FillPatternElement;
                    }
                            
                    mat1.UseRenderAppearanceForShading = m1.UseRenderAppearanceForShading;
                    mat1.StructuralAssetId = asset2.Id;
                    mat1.Color = m1.Color;
                    if (pattern != null)
                    {
                        mat1.CutPatternId = pattern.Id;
                    }
                    mat1.CutPatternColor = m1.CutPatternColor;
                    mat1.AppearanceAssetId = m1.AppearanceAssetId;
                    mat1.SurfacePatternId = m1.SurfacePatternId;
                    mat1.SurfacePatternColor = m1.SurfacePatternColor;                            

                    FamilyParameter fam_param1 = famdoc.FamilyManager.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);

                    if (fam_param1 != null)
                    {
                        famdoc.FamilyManager.Set(fam_param1, mId1);
                    }

                    Parameter doc_param = m1.get_Parameter(BuiltInParameter.FILL_PATTERN_ID_PARAM);
                    FamilyParameter fam_param2 = famdoc.FamilyManager.get_Parameter(BuiltInParameter.FILL_PATTERN_ID_PARAM);

                    if (doc_param != null && fam_param2 != null)
                    {
                        famdoc.FamilyManager.Set(fam_param2, doc_param.AsElementId()); 
                    }

                    if (f.Material2 != null)
                    {
                        Material m2 = Materials.GetMaterials(doc, f.Material2.Name);
                        mId2 = Material.Create(famdoc, f.Material2.Name);

                        if (mId2 != null)
                        {
                            if (f.Material1.Name == "your material name1")
                            {
                                pattern = coll.FirstOrDefault<Element>(e => e.Name.Equals("Steel")) as FillPatternElement;
                            }
                            else if (f.Material1.Name == "your material name2")
                            {
                                pattern = coll.FirstOrDefault<Element>(e => e.Name.Equals("Solid fill")) as FillPatternElement;
                            }

                            Material mat2 = famdoc.GetElement(mId2) as Material;
                            mat2.UseRenderAppearanceForShading = m2.UseRenderAppearanceForShading;
                            mat2.StructuralAssetId = m2.StructuralAssetId;
                            mat2.Color = m2.Color;
                            if (pattern != null)
                            {
                                mat2.CutPatternId = pattern.Id;
                            }
                                    
                            mat2.CutPatternColor = m2.CutPatternColor;
                            mat2.SurfacePatternColor = m2.SurfacePatternColor;

                            FamilyParameter fam_param = famdoc.FamilyManager.AddParameter("Concrete Material", BuiltInParameterGroup.PG_MATERIALS, ParameterType.Material, false);

                            if (fam_param != null)
                            {
                                famdoc.FamilyManager.Set(fam_param, mId2);
                            }
                        }
                    }
                    else
                    {
                        mId2 = null;
                    }

                    if (trans.Commit() == TransactionStatus.Committed)
                    {
                        mIds.Add(mId1);
                        if (mId2 != null)
                        {
                            mIds.Add(mId2);
                        }
                        return mIds;
                    }
                }
            }
            catch (Exception e)
            {
                MessageBox.Show(e.ToString());
            }
        }
    }
    return null;
}

This is the current code that I am using to assign the materials to the family extrusions. Hope it helps. FamilyEntry is just a generic datatype that holds all the stuff I need.

 

 

regards

Christian

Message 10 of 16
dirk.neethling
in reply to: Anonymous

Hello Christian,

 

yes I figured that out now as well. I just have to do this:

 

prm = solid.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM);

isSet = prm.Set(rubber.Id);

 

Thanks for your code. What are the following?

FamilyEntry f

Materials: Materials Collection?

 

No I don't have Revit lookup installed.

 

I would like to assign and use additional Parameters for things like Dates, and Production values and Input from surveying. How can I Access the FamilyParameters which I created when I am in FamilyInstance?

dirk

 

 

 

Message 11 of 16
Anonymous
in reply to: dirk.neethling

FamilyEntry is just my own datatype and the material collection is a list of all available materials in the document.

 

When you create a new FamilyParameter you have it right at this time. If you want to access is later you will need to close the transaction so the parameter gets written to the document/element.

 

regards

Christian

 

PS: Get Revit Lookup. Helps a lot.

Message 12 of 16
dirk.neethling
in reply to: Anonymous

Ok thanks for the info, and I'll get

 

I define a FamilyParameter as follows:

familyParameter = familyMgr.AddParameter("HT_ROTATION_TUNNEL", BuiltInParameterGroup.PG_GEOMETRY, ParameterType.Length, true);

 

When I look for it in the FamilyInstance fi, I cannot find it:

 

IList<Parameter> parms = fi.GetOrderedParameters();

foreach (Parameter parm in parms)

{

 if ((parm.Definition.Name == "HT_ROTATION_TUNNEL"))

  {

   s = string.Format("{0}.{1}", parm.Definition.Name, Globalcounter);

  }

}

 

What is the relationship between FamilyParameter and ordinary builtin-type?

 

Message 13 of 16
Anonymous
in reply to: dirk.neethling

Builtin comes with the template you are using. Custom stuff you need to define.

 

regards

christian

Message 14 of 16
dirk.neethling
in reply to: Anonymous

Ok thanks, one last question:

In your method SetFamilyMaterial, you use bothe built-in and FamilyParameters.

When I use the method it breaks here, because famparam returns null :

 

Parameter param = geo.get_Parameter(BuiltInParameter.MATERIAL_ID_PARAM);

if (param.Set(mId))

{

  FamilyParameter famparam = fm.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);

->if (famparam != null && fm.CanElementParameterBeAssociated(param))

 

Why can't I find

 

famparam = fm.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM);

 

in my Family?

 

I really appreciate your help!

Message 15 of 16
Anonymous
in reply to: dirk.neethling

What type of family template are you using? A structural template like column or framing?

 

Christian

Message 16 of 16
dirk.neethling
in reply to: Anonymous

No, I am using templateName = @"M_Mechanische Geräte.rft";

The english Version is "Metric Mechanical Equipment.rft"

It was the only template which allowed me to rotate and translate the FamilyInstance in 6 degrees of freedom (x,y,z, rot_x,rot_y,rot_z). But it has other drawbacks, such as not containing any usefule Materials.

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

Post to forums  

Forma Design Contest


Rail Community