Parameter of Revit API – 14: Set Parameter Value
Parameter offers a few set methods to assign values to different data types:
Set(ElementId)
Set(Double)
Set(Int32)
Set(String)Obviously, the first signature is used to assign value for Parameter with ElementId StorageType and the last is for String StorageType. The middle two may confuse people: what will happen if a value of 5 is provided to the Set method of a Double StorageType Parameter and what if a value of 5.0 to of Integer StorageType?
Let’s do a simple test: Wall wall = SelectWall(cmdData.Application.ActiveUIDocument.Selection);
List<Parameter> pLst = (from Parameter p in wall.Parameters select p).ToList();string str = string.Empty;
//Double StorageType
Parameter baseOffsetP = pLst.First(p => p.Definition.Name == "Base Offset");
str += "\nDouble StorageType:\n";
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", baseOffsetP.AsDouble(), "2*3", baseOffsetP.Set(2*3), baseOffsetP.AsDouble());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", baseOffsetP.AsDouble(), "5", baseOffsetP.Set(5), baseOffsetP.AsDouble());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", baseOffsetP.AsDouble(), "\"3.3\"", baseOffsetP.Set("3.3"), baseOffsetP.AsDouble());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", baseOffsetP.AsDouble(), "3/1.5", baseOffsetP.Set(3/1.5), baseOffsetP.AsDouble());//Integer StorageType
Parameter strucUsageP = pLst.First(p => p.Definition.Name == "Structural Usage");
str += "\nInteger StorageType:\n";
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", strucUsageP.AsInteger(), "\"2\"", strucUsageP.Set("2"), strucUsageP.AsInteger());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", strucUsageP.AsInteger(), "1.0", strucUsageP.Set(1.0), strucUsageP.AsInteger());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", strucUsageP.AsInteger(), "3*2.1", strucUsageP.Set(3*2.1), strucUsageP.AsInteger());//String StorageType
Parameter markP = pLst.First(p => p.Definition.Name == "Mark");
str += "\nString StorageType:\n";
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", markP.AsString(), "2", markP.Set(2), markP.AsString());
str += string.Format("Before set:{0} \t\tTo:{1} \tRet:{2} \tAfter set:{3}\n", markP.AsString(), "\"3.1\"", markP.Set("3.1"), markP.AsString());MessageBox.Show(str, "Parameter Set Signatures and Results");Some information like the following may be outputted:http://spiderinnet.typepad.com/.a/6a013489b64e31970c01538e2640a3970b-800wi
The results are not as expected or documented, are they? For a Double StorageType Parameter, its Set method can accept an INTEGER argument! For an Integer StorageType Parameter, its Set method accepts a double value, 1.0!
The trickiest part is the return values in all these cases are all TRUE!It is good that the Parameter.Set() method offers some flexibility but at the same time it brings confusion. Similar situation is with the SetValueString() method.The following might not make much sense but they do make things clearer:SetElementId(ElementId)
SetDouble(Double)
SetInteger(Int32)
SetString(String)If the flexibility has higher priority, a method like the following is obviously better:
public static void SetParameterValue(Parameter p, object value)
{
try
{
if (value.GetType().Equals(typeof(string)))
{
if (p.SetValueString(value as string))
return;
} switch (p.StorageType)
{
case StorageType.None:
break;
case StorageType.Double:
if (value.GetType().Equals(typeof(string)))
{
p.Set(double.Parse(value as string));
}
else
{
p.Set(Convert.ToDouble(value));
}
break;
case StorageType.Integer:
if (value.GetType().Equals(typeof(string)))
{
p.Set(int.Parse(value as string));
}
else
{
p.Set(Convert.ToInt32(value));
}
break;
case StorageType.ElementId:
if (value.GetType().Equals(typeof(ElementId)))
{
p.Set(value as ElementId);
}
else if (value.GetType().Equals(typeof(string)))
{
p.Set(new ElementId(int.Parse(value as string)));
}
else
{
p.Set(new ElementId(Convert.ToInt32(value)));
}
break;
case StorageType.String:
p.Set(value.ToString());
break;
}
}
catch
{
throw new Exception("Invalid Value Input!");
}
}All possible good values will be accepted and the best intelligence can be achieved. The following code can be used to exercise the help method:
Wall wall = SelectWall(cmdData.Application.ActiveUIDocument.Selection);
List<Parameter> pLst = (from Parameter p in wall.Parameters select p).ToList();//Double StorageType
Parameter baseOffsetP = pLst.First(p=>p.Definition.Name == "Base Offset");
SetParameterValue(baseOffsetP, "2'3\"");
SetParameterValue(baseOffsetP, "15");
SetParameterValue(baseOffsetP, "14.7");
SetParameterValue(baseOffsetP, 11);
SetParameterValue(baseOffsetP, 7.1);
try
{
SetParameterValue(baseOffsetP, "abc");
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}//Integer StorageType
Parameter strucUsageP = pLst.First(p => p.Definition.Name == "Structural Usage");
SetParameterValue(strucUsageP, "2");
SetParameterValue(strucUsageP, 1.0);
SetParameterValue(strucUsageP, 2L);
SetParameterValue(strucUsageP, 0);
try
{
SetParameterValue(strucUsageP, wall);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}//String StorageType
Parameter markP = pLst.First(p => p.Definition.Name == "Mark");
SetParameterValue(markP, "Test by Spiderinnet");
SetParameterValue(markP, 123456.789);
SetParameterValue(markP, 2L);
SetParameterValue(markP, wall);
try
{
SetParameterValue(markP, null);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}If an extension method for the Parameter class seems better, here it is:#region Namespacesusing System;
using System.Text;
using System.Linq;
using System.Xml;
using System.Reflection;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Windows.Forms;
using System.IO;using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.Attributes;using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Events;
using Autodesk.Revit.DB.Architecture;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Plumbing;using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using Autodesk.Revit.UI.Events;using Autodesk.Revit.Collections;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.Utility;using RvtApplication = Autodesk.Revit.ApplicationServices.Application;
using RvtDocument = Autodesk.Revit.DB.Document;#endregionnamespace RevitAddinCS
{
public static class ParameterExtension
{
public static void SetValue(this Parameter p, object value)
{
try
{
if (value.GetType().Equals(typeof(string)))
{
if (p.SetValueString(value as string))
return;
} switch (p.StorageType)
{
case StorageType.None:
break;
case StorageType.Double:
if (value.GetType().Equals(typeof(string)))
{
p.Set(double.Parse(value as string));
}
else
{
p.Set(Convert.ToDouble(value));
}
break;
case StorageType.Integer:
if (value.GetType().Equals(typeof(string)))
{
p.Set(int.Parse(value as string));
}
else
{
p.Set(Convert.ToInt32(value));
}
break;
case StorageType.ElementId:
if (value.GetType().Equals(typeof(ElementId)))
{
p.Set(value as ElementId);
}
else if (value.GetType().Equals(typeof(string)))
{
p.Set(new ElementId(int.Parse(value as string)));
}
else
{
p.Set(new ElementId(Convert.ToInt32(value)));
}
break;
case StorageType.String:
p.Set(value.ToString());
break;
}
}
catch
{
throw new Exception("Invalid Value Input!");
}
} }
}
And the following code can be used to exercise the extension method:Wall wall1 = SelectWall(cmdData.Application.ActiveUIDocument.Selection);
List<Parameter> pLst1 = (from Parameter p in wall1.Parameters select p).ToList();//Double StorageType
Parameter baseOffsetP1 = pLst1.First(p => p.Definition.Name == "Base Offset");
baseOffsetP1.SetValue("2'3\"");
baseOffsetP1.SetValue("15");
baseOffsetP1.SetValue("14.7");
baseOffsetP1.SetValue(11);
baseOffsetP1.SetValue(7.1);
try
{
baseOffsetP1.SetValue("abc");
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}//Integer StorageType
Parameter strucUsageP1 = pLst1.First(p => p.Definition.Name == "Structural Usage");
strucUsageP1.SetValue("2");
strucUsageP1.SetValue(1.0);
strucUsageP1.SetValue(2L);
strucUsageP1.SetValue(0);
try
{
strucUsageP1.SetValue(wall);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}//String StorageType
Parameter markP1 = pLst1.First(p => p.Definition.Name == "Mark");
markP1.SetValue("Test by Spiderinnet");
markP1.SetValue(123456.789);
markP1.SetValue(2L);
markP1.SetValue(wall);
try
{
markP1.SetValue(null);
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}Parameter Writer of RevitAddinWizardwill provide the intelligence in no time.
顶......
楼下跟上.....
页:
[1]