We have talked about various aspects of each parameter kind such as element parameter, family parameter, shared parameter, and project parameter of Revit API. From now on, let’s see the programmatic interchangeability between any two kinds of these Revit parameters.
Before creating the specific code for the Parameter Converter, we need to put some Coders together first that we introduced and demonstrated before. They will save us a lot of precious time and avoid duplicate effort.
Revit Parameter Organizer can organize various Revit parameters such as Shared Parameters, Family Parameters, Project Parameters and Built-in Parameter in many good ways.
Here they are:
#region From Parameter Infoer
public class RawParameterInfo
{
public string Name { get; set; }
public string Value { get; set; }
public BuiltInParameterGroup Group { get; set; }
public ParameterType Type { get; set; }
public StorageType Storage { get; set; }
public string Unit { get; set; }
public bool Shared { get; set; }
public string ID { get; set; }
public bool ReadOnly { get; set; }
}
public static string RawGetDUTString(Parameter p)
{
string unitType = string.Empty;
try { unitType = p.DisplayUnitType.ToString(); }
catch { }
return unitType;
}
public static List<RawParameterInfo> RawGetParametersInfo(Element e)
{
List<RawParameterInfo> paramList =
(from Parameter p in e.Parameters
select new RawParameterInfo
{
Name = p.Definition.Name,
Value = p.AsValueString(),
Group = p.Definition.ParameterGroup,
Type = p.Definition.ParameterType,
Storage = p.StorageType,
Unit = RawGetDUTString(p),
Shared = p.IsShared,
ReadOnly = p.IsReadOnly,
ID = p.IsShared ? p.GUID.ToString() :
(p.Definition as InternalDefinition).BuiltInParameter.ToString()
}).ToList();
return paramList;
}
#endregion
#region From SharedParameter Creator
public static List<T> RawConvertSetToList<T>(IEnumerable set)
{
List<T> list = (from T p in set select p).ToList<T>();
return list;
}
public static Definition RawCreateSharedParameter(RvtApplication app, string name, string group, ParameterType type, bool visible)
{
DefinitionFile defFile = app.OpenSharedParameterFile();
if (defFile == null) throw new Exception("No SharedParameter File!");
DefinitionGroup dg = RawConvertSetToList<DefinitionGroup>(defFile.Groups).FirstOrDefault(g => g.Name == group);
if (dg == null) dg = defFile.Groups.Create(group);
Definition def = RawConvertSetToList<Definition>(dg.Definitions).FirstOrDefault(d => d.Name == name);
if (def != null) return def; //dg.Definitions.Erase(def); //ReadOnly Exception!!
def = dg.Definitions.Create(name, type, visible);
return def;
}
#endregion
#region From Object Picker
public static Reference SelectAnyElement(Selection selection)
{
Reference picked = selection.PickObject(ObjectType.Element, "Select an Element of any type");
return picked;
}
#endregion
With all the above code handy, it becomes a pretty easy task to create some code to convert a particular paramter or all parameters of a Revit Element to shared parameters:
public static void ConvertParameterToSharedParameter(Element e, string name, bool convertSharedOnly, bool visibilityOverride)
{
List<RawParameterInfo> pList = RawGetParametersInfo(e);
List<RawParameterInfo> pListOfInterest = pList.FindAll(p => p.Name == name);
foreach (RawParameterInfo info in pListOfInterest)
{
if (info.Type == ParameterType.Invalid)
{
info.Type = ParameterType.Text; //It's weird that a valid Parameter can have an invalid ParameterType! We set it as the most popular Text type in this case. Otherwise, the DefinitionGroup.Definitions.Create() would fail!
}
if (convertSharedOnly)
{
if (info.Shared)
{
RawCreateSharedParameter(e.Document.Application, name, "For_" + e.Category.Name, info.Type, visibilityOverride);
}
}
else
{
RawCreateSharedParameter(e.Document.Application, name, "For_" + e.Category.Name, info.Type, visibilityOverride);
}
}
}
public static void ConvertAllParametersToSharedParameters(Element e, bool convertSharedOnly, bool visibilityOverride)
{
List<RawParameterInfo> pList = RawGetParametersInfo(e);
foreach (RawParameterInfo info in pList)
{
if (info.Type == ParameterType.Invalid)
{
info.Type = ParameterType.Text; //It's weird that a valid Parameter can have an invalid ParameterType! We set it as the most popular Text type in this case. Otherwise, the DefinitionGroup.Definitions.Create() would fail!
}
if (convertSharedOnly)
{
if (info.Shared)
{
RawCreateSharedParameter(e.Document.Application, info.Name, "For_" + e.Category.Name, info.Type, visibilityOverride);
}
}
else
{
RawCreateSharedParameter(e.Document.Application, info.Name, "For_" + e.Category.Name, info.Type, visibilityOverride);
}
}
}
A few points may be worth of mentioning here:
- The ParameterType of some valid Parameter instances may be Invalid! We assign the most popular Text ParameterType to the Parameter instances in this case to resolve the creation problem of shared parameters.
- The name of the DefinitionGroup of all the shared parameters will be defaulted as For_<Category Name> of the picked element.
- Since the visibility information of the original shared parameter definitions is nowhere to find, we provide a chance in these methods to override it for the shared parameters going to be created.
The following test code can exercise the methods:
Element e = SelectAnyElement(CachedUiApp.ActiveUIDocument.Selection).Element;
//ConvertParameterToSharedParameter(e, "Volume41", true, true);
ConvertAllParametersToSharedParameters(e, false, true);
In terms of details of the various coders referenced in this post please refer to previous posts for ideas and code examples.
Parameter Converter of RevitAddinWizard can create all these in a second.
Recent Comments