AutoCAD has supported the eXtended Data for long time, back to the ADS era. In the AutoCAD .NET world, those functionalities regarding the XData manipulations and even those extended DXF codes are wrapped nicely into some classes, structs, methods and enums.
However, because of the different syntaxes in the new AutoCAD .NET and the old ADS, even for people coming from the ADS time and using those old ResultBuffer a lot, they may still be confused about some classes, methods, and enum values as far as XData and ResultBuffer are concerned.
Even for a simple task like removing all existing XData from an Entity, things are not as expected by people. In this post, let’s try to remove all XData from an entity first with various ways that look natural and straightforward and finally suggest the way as designed!
Ok, the trails and errors go first.
[CommandMethod("TryToRemoveAllXDataFromEntity")]
public static void TryToRemoveAllXDataFromEntity_Method()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
try
{
PromptEntityResult prEntRes = ed.GetEntity("\nSelect an Entity to remove all XDATA from");
if (prEntRes.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = (Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
if (ent.XData != null)
{
ent.UpgradeOpen();
ent.XData.Dispose();
ent.XData = new ResultBuffer();
ent.XData = null;
}
else
ed.WriteMessage("\nNo XData to delete.");
tr.Commit();
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
As can be seen, three ordinary ways, disposing of the XData instance, setting the XData as a new empty ResultBuffer, and setting the XData property as null (or Nothing in VB.NET), have been tried in the above command/code. However, none of these approaches would take any effect to the XData of the picked entity if the command being tried.
Now the as-design approach comes below.
[CommandMethod("RemoveAllXDataFromEntity")]
public static void RemoveAllXDataFromEntity_Method()
{
Database db = HostApplicationServices.WorkingDatabase;
Editor ed = MgdAcApplication.DocumentManager.MdiActiveDocument.Editor;
try
{
PromptEntityResult prEntRes = ed.GetEntity("\nSelect an Entity to remove all XDATA from");
if (prEntRes.Status == PromptStatus.OK)
{
using (Transaction tr = db.TransactionManager.StartTransaction())
{
Entity ent = (Entity)tr.GetObject(prEntRes.ObjectId, OpenMode.ForRead);
if (ent.XData != null)
{
IEnumerable<string> appNames = from TypedValue tv in ent.XData.AsArray() where tv.TypeCode == 1001 select tv.Value.ToString();
ent.UpgradeOpen();
foreach (string appName in appNames)
{
ent.XData = new ResultBuffer(new TypedValue(1001, appName));
}
ed.WriteMessage("\nAll XData have been deleted.");
}
else
ed.WriteMessage("\nNo XData to delete.");
tr.Commit();
}
}
}
catch (System.Exception ex)
{
ed.WriteMessage(ex.ToString());
}
}
It works as designed or expected by some people but does not look natural at all to .NET programmers. People coming from the ADS and C/C++ legacy world should know something about it why we have to do this way.
To make .NET API really .NET, apparently should something more have been done rather than simply wrap around those legacy ADS/C stuffs.
The leading edge AutoCAD .NET Addin Wizard (AcadNetAddinWizard) provides project wizards in C#, VB.NET and CLI/Managed C++, and various item wizards such as Event Handlers, Command/LispFunction Definers, and Entity/Draw Jiggers in both C# and VB.NET, to help program AutoCAD addins.
Hi,
there is two examples to do same thing.
How to remove xdata attached to an entity regardless of the appname using ObjectARX or LISP?
void removeXdata()
{
ads_name eNam;
ads_point pt;
int i = acedEntSel ("\nPick an object:", eNam, pt);
if (RTNORM != i)
{
return;
}
AcDbObjectId ObjId;
acdbGetObjectId(ObjId, eNam);
AcDbEntity *pEnt = NULL;
Acad::ErrorStatus es = acdbOpenAcDbEntity(pEnt, ObjId, AcDb::kForWrite);
resbuf *xdata = pEnt->xData(NULL);
if (xdata)
{
xdata->rbnext = NULL;
pEnt->setXData(xdata);
acutRelRb(xdata);
}
pEnt->close();
}
Here is some Lisp Code to remove the Xdata from a selected object:
(defun c:DelXdata()
(setq l (car (entsel "Pick object:")))
(if l (progn
(redraw l 3)
(setq le (entget l '("*")) )
(setq xdata (assoc '-3 le))
(setq le
(subst (cons (car xdata) (list (list (car (car (cdr xdata)))))) xdata le))
(entmod le)
(redraw l 4)
le
)
)
)
NOTE: However if the entity has multiple XDATA's attached, this sample code will remove only one XDATA for every execution. You can modify it to remove all the XDATA's attached by iterating through them.
Posted by: Veli Väisänen | 01/18/2013 at 03:26 AM
Veli, thanks for suggesting the ObjectARX and the AutoLISP approaches as well. All these made the story almost complete.
It may also be worth to try the same with AutoCAD COM/ActiveX API.
Posted by: Spiderinnet1 | 01/18/2013 at 04:42 AM