Some of our guys have made the mistake of binding the xrefs into the current drawing and saving; overwriting the current file. It has been asked if it is possible to create a command that binds all the loaded xrefs into the current drawing, saving as a different file.
That's not really the problem. The guys are needing the original drawing (unbound) kept open/reopened in the editor after closing the bound version!
I am using VS2005, .NET 2.0 and AutoCAD 2008.
Code to bind all xrefs into the current drawing: (converted from VB)
public static bool BindAllXRefs()
{
//Get the active document
Autodesk.AutoCAD.ApplicationServices.Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
//Get the active database
Database db = doc.Database;
//Get the xref graph
XrefGraph xrefg = db.GetHostDwgXrefGraph(true);
//Check if the xref graph is empty or contains just the current drawing
if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
return false;
return; // TODO: might not be correct. Was : Exit Function
}
//Start a new transaction to get the exreferences
using (Transaction tr = doc.TransactionManager.StartTransaction) {
//Get the current block table
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
//Loop through all the xrefs in the block table
for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
//Get the graph node
XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
//Only bind loaded xrefs
if (!(xrefn.XrefStatus == XrefStatus.Unloaded)) {
//Get the blocktable record
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrefn.BlockTableRecordId, OpenMode.ForWrite, false);
//Get any inserted xrefs
ObjectIdCollection BlkRefCollection = btr.GetBlockReferenceIds(true, true);
//If the block exists then add and bind
if (BlkRefCollection.Count > 0) {
ObjectIdCollection ObjIdCollection = new ObjectIdCollection();
//Add the object id to the collection
ObjIdCollection.Add(btr.Id);
//Do the bind
db.BindXrefs(ObjIdCollection, true);
}
else {
//Detach the xrefs if not loaded
db.DetachXref(btr.Id);
}
}
}
tr.Commit();
return true;
}
}
I tried the following 'horrible' workaround attempt; the idea of which was to work on a temporary copy of the drawing:
public static bool BindDrawing(string OpenFileName, string SaveFileName)
{
//Open the database transparently
string tempname = "C:\\temp.dwg";
System.IO.File.Copy(OpenFileName, tempname);
using (Database db = new Database(false, true)) {
//Read in the drawing file
db.ReadDwgFile(tempname, System.IO.FileShare.Read, true, null);
//Set the current working database
if (db != HostApplicationServices.WorkingDatabase) {
HostApplicationServices.WorkingDatabase = db;
}
//Get the xref graph
XrefGraph xrefg = db.GetHostDwgXrefGraph(true);
//Check if the xref graph is empty (contains just the current drawing)
if (xrefg.IsEmpty || xrefg.NumNodes == 1) {
//We don't need to bind, so discard the database
db.Dispose();
return true;
return; // TODO: might not be correct. Was : Exit Function
}
//Drawing has ex-references
//Start a new transaction
using (Transaction tr = db.TransactionManager.StartTransaction) {
//Get the block table of the database
BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
//Loop through the records in the block table to get all the xrefs
for (int i = 1; i <= xrefg.NumNodes - 1; i++) {
//Get the graph node
XrefGraphNode xrefn = (XrefGraphNode)xrefg.GetXrefNode(i);
//Only bind the loaded xrefs
if (!(xrefn.XrefStatus == XrefStatus.Unloaded)) {
//Get the block table record that matches the xref node reference
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(xrefn.BlockTableRecordId, OpenMode.ForWrite, false);
ObjectIdCollection BlkRefCollection = btr.GetBlockReferenceIds(true, true);
//If the xref exists as a block table record then add and bind
if (BlkRefCollection.Count > 0) {
ObjectIdCollection ObjIDCollection = new ObjectIdCollection();
//Add the object id to the collection
ObjIDCollection.Add(btr.Id);
//Do the bind
db.BindXrefs(ObjIDCollection, true);
}
else {
//Detach the xref if not loaded
db.DetachXref(btr.Id);
}
}
}
tr.Commit();
}
db.RetainOriginalThumbnailBitmap = true;
db.SaveAs(SaveFileName, DwgVersion.Current);
db.CloseInput(true);
}
HostApplicationServices.WorkingDatabase = AppServices.DocumentManager.MdiActiveDocument.Database;
}
Some of the code used in the second method came from this site (Thanks Draftek).
This does not work as expected, in fact it doesn't bind in some cases!