CAD.NET中使用XBindXrefs、BindXrefs双重绑定参照的探讨
* (注:本文仅为自己在实际工作中遇到的问题,所找到的一种解决方案,仅供参考、学习使用。若有不足处,欢迎在评论区留言纠正)
* 一、CAD原BindXrefs方法可直接对外部参照BlockTable的id集合绑定,当使用其绑定xrNode.BlockTableRecordId的集合或btr.ObjectId的集合时,往往会出现无法意料的异常,如eInvalidInput、eNullObjectId、eWrongObjectType
* 或各种图层复原等,导致外部参照不能完全绑定,从而达不到图纸的绑定期望。
*
* 二、例如本人遇到的外部参照绑定后图层复原问题、绑定不彻底问题,它俩并不是每次绑定都会出现,而是不一样的图纸,随机发生,只要一出现,原图纸无论怎样处理,再绑定也不能消除异常,即这些问题具有不可预测性。
* 怎样来处理诸如以上描述的问题,一直是棘手的事,也曾通过微软bing、CAD二次开发群等方式搜索、咨询XBindXrefs方法使用相关资料,未找到合理的解决方案。
*
* 三、根据CAD在线帮助文件对XBindXrefs方法描述“The ObjectIds in xrefSymbolIds must all be from the working database and they must all be from resolved xrefs”中发现,需要转换数据库后,再对参照符号表记录id
* 集合绑定。且根据该方法对第一个参数的描述“Input collection of ObjectIds of SymbolTableRecord objects to be bound”,注意到应正确使用XBindXrefs和BindXrefs的顺序。结合“xrefSymbolIds may contain ObjectIds
* for the following symbol table record types: BlockTableRecord, LayerTableRecord, LinetypeTableRecord, TextStyleTableRecord (if it does not represent a shape file),RegAppTableRecord, and DimStyleTableRecord”
* 的描述,其中虽含块表记录,经实测,CAD原XBindXrefs方法仅可对图层表记录、线性表记录、文字样式表记录、注册程序表记录、标注样式表记录进行绑定,除对符号表中的用户坐标系表记录、视口表记录、视图表记录是不能绑定外,
* 块表记录却也不能绑定,否则会出现eWrongObjectType异常。
*
* 四、最后经本人实际测试,得出CAD原生XBindXrefs和BindXrefs的结合使用可解决上述大部分异常问题的方式和注意事项,整理如下:
* 1)结合使用须前置的条件:数据库转换,利用WorkingDatabase;
* 2)使用顺序:先XBindXrefs,再BindXrefs;
* 3)关于XBindXrefs可绑定的5个符号表记录累加绑定效果:
* a、单选XBindXrefs绑定图层表记录,可以解决绝大部分图纸的绑定(本人暂未遇到不能绑定的情况,本选项为“无敌绑定”项)。
* b、在选用a项绑定时,可能遇到的情况是,如属性文字偏移(本人遇到),很少部分图纸会出现,解决方法是选XBindXrefs绑定图层表记录、文字样式表记录即可。
* c、除选用a项绑定,若单个单个累加其他剩下4个符号表记录,大部分图纸能正常绑定,少数图纸会出现eWrongObjectType异常,建议根据所需动态选择绑定的符号表记录。
* d、除选用a项绑定,其他4个符号表记录,一一单选绑定,本人未进行测试,所需者可根据自身要求测试绑定效果。
*
* 五、附本人测试成功的封装代码。该文为本人第一原创,如有引用或转载本文,请标识出处。QQ1039574776。
*/
using Autodesk.AutoCAD.DatabaseServices; using System.Collections.Generic; using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application; namespace Oncet.CAD { public static class XrefEx { /// <summary> /// XBindXrefs、BindXrefs双重绑定参照。增加绑定符号表累计的选择;增加储存嵌套参照被卸载的字典ref方式 /// </summary> /// <param name="db">数据库</param> /// <param name="symbolTableRecordNum">累计要绑定的符号表数量,默认为0。最小为0,最大为4。具体【0为"图层表",1为"文字样式表",2为"线型表",3为"注册应用程序表",4为"标注样式表"】</param> /// <param name="isNestedNodeNameDic">储存嵌套参照被卸载的字典</param> public static void XBindXrefs(Database db, ref Dictionary<Handle, string> isNestedNodeNameDic, int symbolTableRecordNum = 0) { //数据库转换 var workingDb = HostApplicationServices.WorkingDatabase; HostApplicationServices.WorkingDatabase = db; string errorRemark = db.OriginalFileName;//标记可能出错的文件名,在异常时使用; Dictionary<Handle, string> isNestedNodeName = isNestedNodeNameDic; try { db.ResolveXrefs(false, false);//解析数据库 var bindXrefsIds = new ObjectIdCollection();//声明要BindXrefs的集合 var xBindXrefsIds = new ObjectIdCollection();//声明要XBindXrefs的集合 ObjectIdCollection isNestedIds = new ObjectIdCollection();//20220815 using (var tr = db.TransactionManager.StartTransaction()) { #region MyRegion20220815-批注原块表参照的id集合获取 var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);//块表 foreach (ObjectId id in bt) { var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); if (btr.IsFromExternalReference && btr.IsResolved) bindXrefsIds.Add(id); } #endregion #region MyRegion20220815补充是否被嵌套卸载的处理 XrefGraph xg = db.GetHostDwgXrefGraph(true); int xrefcount = xg.NumNodes; for (int j = 0; j < xrefcount; j++) { XrefGraphNode xrNode = xg.GetXrefNode(j); if (xrNode.XrefStatus == XrefStatus.Unloaded)//若文件已卸载 { ObjectId deTachId = xrNode.BlockTableRecordId; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(deTachId, OpenMode.ForRead); if (btr.IsFromExternalReference) { if (!xrNode.IsNested)//若为非嵌套参照 { db.DetachXref(deTachId);//拆离已经卸载的非嵌套文件 } if (xrNode.IsNested)//若为嵌套参照 { isNestedIds.Add(deTachId); isNestedNodeName.Add(deTachId.Handle, xrNode.Name);//有嵌套参照,添加关键信息进字典,以传出方法供绑定后删除处理 } } } if (xrNode.XrefStatus == XrefStatus.Unreferenced)//若文件未参照 { db.DetachXref(xrNode.BlockTableRecordId);//拆离未参照的文件 } #region MyRegion使用此方法添加的xrNode.BlockTableRecordId,绑定中会随机出现异常(勿用) //if (xrNode.XrefStatus == XrefStatus.Resolved)//若文件已解析 //{ // ObjectId bindXrefId = xrNode.BlockTableRecordId; // BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bindXrefId, OpenMode.ForRead); // if (btr.IsFromExternalReference) // { // xrefIds.Add(bindXrefId); // } //} #endregion } #endregion #region MyRegion20220814添加XBindXrefs符号表记录id。根据symbolTableRecordNum值范围0~4动态控制5个符号表记录累加绑定需求 if (symbolTableRecordNum >= 0)//为0时被本人称为“无敌绑定”项 { LayerTable layert = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;//图层表 foreach (ObjectId id in layert) { LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead); if (ltr.IsResolved) { xBindXrefsIds.Add(ltr.ObjectId); } } } if (symbolTableRecordNum >= 1) { TextStyleTable textstylet = tr.GetObject(db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable;//文字样式表 foreach (ObjectId id1 in textstylet) { TextStyleTableRecord textstyletr = (TextStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (textstyletr.IsResolved) { xBindXrefsIds.Add(textstyletr.ObjectId); } } } if (symbolTableRecordNum >= 3) { LinetypeTable linetypet = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;//线型表 foreach (ObjectId id1 in linetypet) { LinetypeTableRecord linetr = (LinetypeTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (linetr.IsResolved) { xBindXrefsIds.Add(linetr.ObjectId); } } } if (symbolTableRecordNum >= 2) { DimStyleTable dimt = tr.GetObject(db.DimStyleTableId, OpenMode.ForRead) as DimStyleTable;//标注样式表 foreach (ObjectId id1 in dimt) { DimStyleTableRecord dtr = (DimStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (dtr.IsResolved) { xBindXrefsIds.Add(dtr.ObjectId); } } } if (symbolTableRecordNum >= 4) { RegAppTable regappt = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;//注册应用程序表 foreach (ObjectId id1 in regappt) { RegAppTableRecord regapptr = (RegAppTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (regapptr.IsResolved) { xBindXrefsIds.Add(regapptr.ObjectId); } } } #region MyRegion20220814起初测试是将9大符号表记录均加入的,但经实测不行。所以根据截取帮助文件中描述,仅添加了块表外的5表记录id ///xrefSymbolIds可能包含以下符号表记录类型的 ObjectId: ///BlockTableRecord、LayerTableRecord、LinetypeTableRecord、TextStyleTableRecord(如果它不代表形状文件)、RegAppTableRecord和DimStyleTableRecord。 ///20220814 //ViewportTable viewport = tr.GetObject(db.ViewportTableId, OpenMode.ForRead) as ViewportTable;//视口表 //foreach (ObjectId id1 in viewport) //{ // ViewportTableRecord viewportr = (ViewportTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (viewportr.IsResolved) // { // xrefIds1.Add(viewportr.ObjectId); // } //} //ViewTable viewt = tr.GetObject(db.ViewTableId, OpenMode.ForRead) as ViewTable;// 视图表 //foreach (ObjectId id1 in viewt) //{ // ViewTableRecord viewtr = (ViewTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (viewtr.IsResolved) // { // xrefIds1.Add(viewtr.ObjectId); // } //} //UcsTable ucst = tr.GetObject(db.UcsTableId, OpenMode.ForRead) as UcsTable;// 用户坐标系表 //foreach (ObjectId id1 in ucst) //{ // UcsTableRecord ucstr = (UcsTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (ucstr.IsResolved) // { // xrefIds1.Add(ucstr.ObjectId); // } //} #endregion #endregion } if (isNestedIds.Count > 0)//若有嵌套参照被卸载,重载 { db.ReloadXrefs(isNestedIds); } #region MyRegion20220814此处即为二者结合使用,且顺序非常重要。若交换秩序,则会绑定无效,切勿交换!!! db.XBindXrefs(xBindXrefsIds, true);//20220814建议为true db.BindXrefs(bindXrefsIds, true);//20220814建议为true #endregion } catch (System.Exception ex) { throw new System.Exception(ex.Message); //AcCoreAp.ShowAlertDialog("Error: " + ex.Message); } finally { isNestedNodeNameDic = isNestedNodeName;//20220815 HostApplicationServices.WorkingDatabase = workingDb; } } } }
后续1:
根据Q群ifoxcad(QQ718996771)群友反馈,补充了最简测试代码,具体如下
using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Runtime; using System.Collections.Generic; using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application; namespace Oncet.CAD { public class _20220817测试 { [CommandMethod("MyXBindXrefs")]//20220817后台绑定最简测试代码(图纸仅绑定,不做其他处理,如清理、关图层、删除嵌套被卸载的参照等) public static void MyXBindXrefs() { string filePath = @"C:\主屏幕\20220817绑定测试文件.dwg"; using (var db = new Database(false, true)) { Dictionary<Handle, string> isNestedNodeNameDic = new Dictionary<Handle, string>();//用于后期删除嵌套被卸载的参照 db.ReadDwgFile(filePath, FileOpenMode.OpenForReadAndAllShare, false, null); XrefEx.XBindXrefs(db, ref isNestedNodeNameDic, 0);//首选项0 db.SaveAs(filePath, true, db.OriginalFileVersion, db.SecurityParameters);//保存图纸 } } [CommandMethod("MyXBindXrefs1")]//20220817前台绑定最简测试代码(图纸仅绑定,不做其他处理,如清理、关图层、删除嵌套被卸载的参照等) public static void MyXBindXrefs1() { Document Doc = AcadApp.DocumentManager.MdiActiveDocument; Editor ed = Doc.Editor; Database acdb = Doc.Database; Dictionary<Handle, string> isNestedNodeNameDic = new Dictionary<Handle, string>();//用于后期删除嵌套被卸载的参照 XrefEx.XBindXrefs(acdb, ref isNestedNodeNameDic, 0);//首选项0 acdb.SaveAs(Doc.Name, true, acdb.OriginalFileVersion, acdb.SecurityParameters);//保存图纸 } } }
后续2:
20220820补充更新了代码的2个重载和一个清理方法,也可详gitee仓库链接。
/// <summary> /// 表示累计要绑定符号表类型数量的枚举 /// 最小为0,最大为4 /// 具体【0为"图层表",1为"文字样式表",2为"标注样式表",3为"线型表",4为"注册应用程序表"】 /// 如选择TextStyleTable = 1,则表示累计要绑定图层表和文字样式表,以此类推 /// </summary> public enum XrefSymTabTypeNum { /// <summary> /// 图层表,"无敌绑定"项 /// </summary> LayerTable = 0, /// <summary> /// 文字样式表 /// </summary> TextStyleTable = 1, /// <summary> /// 标注样式表 /// </summary> DimStyleTable = 2, /// <summary> /// 线性表 /// </summary> LinetypeTable = 3, /// <summary> /// 注册应用程序表 /// </summary> RegAppTable = 4 } /// <summary> /// 双重绑定参照扩展类 /// <summary> public static class XrefEx { /// <summary> /// 利用两个原生方法双重绑定参照 /// 可内部删除被卸载的嵌套参照 /// 该方法仅用于"无敌绑定"项,其他项有异常eWasOpenForNotify /// </summary> /// <param name="db">数据库</param> /// <param name="isEaseNested">询问是否删除被卸载的嵌套参照,默认为true /// 主要用于处理要绑定图纸中存在嵌套参照被卸载的情况 /// 若为false,则嵌套参照将被重载绑定后保留在图纸中</param> /// <returns>无返回值</returns> public static void XBindXrefs(Database db, bool isEaseNested = true) { var workingDb = HostApplicationServices.WorkingDatabase;//数据库转换 HostApplicationServices.WorkingDatabase = db;//数据库转换 db.ResolveXrefs(false, false);//解析数据库 var bindXrefsIds = new ObjectIdCollection();//要BindXrefs的集合 var xBindXrefsIds = new ObjectIdCollection();//要XBindXrefs的集合 var isNestedNodeNameList = new List<string>();//要处理的嵌套参照名称列表 var isNestedIds = new ObjectIdCollection();//要处理的嵌套参照ObjectId集合 using (var tr = db.TransactionManager.StartTransaction()) { #region 原块表参照的id集合获取 var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);//块表 foreach (ObjectId id in bt) { var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); if (btr.IsFromExternalReference && btr.IsResolved) bindXrefsIds.Add(id); } #endregion #region 补充是否被嵌套卸载的处理 XrefGraph xg = db.GetHostDwgXrefGraph(true); int xrefcount = xg.NumNodes; for (int j = 0; j < xrefcount; j++) { XrefGraphNode xrNode = xg.GetXrefNode(j); if (xrNode.XrefStatus == XrefStatus.Unloaded)//若文件已卸载 { ObjectId deTachId = xrNode.BlockTableRecordId; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(deTachId, OpenMode.ForRead); if (btr.IsFromExternalReference) { if (!xrNode.IsNested)//若为非嵌套参照 { db.DetachXref(deTachId);//拆离已经卸载的非嵌套文件 } else //若为嵌套参照 { isNestedIds.Add(deTachId); isNestedNodeNameList.Add(xrNode.Name);//有嵌套参照,添加名称进列表,以供绑定后是否做删除处理 } } } if (xrNode.XrefStatus == XrefStatus.Unreferenced)//若文件未参照 { db.DetachXref(xrNode.BlockTableRecordId);//拆离未参照的文件 } #region 使用此方法添加的xrNode.BlockTableRecordId,绑定中会随机出现异常(勿用) //if (xrNode.XrefStatus == XrefStatus.Resolved)//若文件已解析 //{ // ObjectId bindXrefId = xrNode.BlockTableRecordId; // BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bindXrefId, OpenMode.ForRead); // if (btr.IsFromExternalReference) // { // xrefIds.Add(bindXrefId); // } //} #endregion } #endregion #region "无敌绑定"项 LayerTable layert = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;//图层表 foreach (ObjectId id in layert) { LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead); if (ltr.IsResolved) { xBindXrefsIds.Add(ltr.ObjectId); } } #endregion if (isNestedIds.Count > 0)//若有嵌套参照被卸载,重载 { db.ReloadXrefs(isNestedIds); } #region 此处即为二者结合使用,且顺序非常重要。若交换秩序,则会绑定无效,切勿交换 db.XBindXrefs(xBindXrefsIds, true);//建议为true db.BindXrefs(bindXrefsIds, true);//建议为true #endregion #region 内部删除嵌套参照的块操作 if (isEaseNested) { if (isNestedNodeNameList != null && isNestedNodeNameList.Count > 0) { isNestedNodeNameList.ForEach(blockName => { if (bt.Has(blockName)) { BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt[blockName], OpenMode.ForWrite); if (btr != null) { btr.Erase(); } } }); } } #endregion } HostApplicationServices.WorkingDatabase = workingDb;//数据库转换 } /// <summary> /// 利用两个原生方法双重绑定参照 /// 1.增加绑定符号表累计的选择,LayerTable=0时,即单选图层表为"无敌绑定"项 /// 2.增加储存被卸载嵌套参照名称及句柄的字典,以ref方式传出方法 /// 提供外部处理嵌套参照的数据,绑定后若不处理,则将被保留在图纸中 /// </summary> /// <param name="db">数据库</param> /// <param name="isNestedNodeNameDic">储存被卸载嵌套参照名称及句柄的字典 /// 主要用于处理要绑定图纸中存在嵌套参照被卸载的情况</param> /// <param name="xrefSymTabTypeNum">累计要绑定的符号表数量,默认为LayerTable=0"无敌绑定"项.最小为0,最大为4 /// 具体【0为"图层表",1为"文字样式表",2为"标注样式表",3为"线型表",4为"注册应用程序表"】</param> /// <returns>无返回值,以ref方式传出被卸载嵌套参照名称及句柄的字典</returns> public static void XBindXrefs(Database db, ref Dictionary<Handle, string> isNestedNodeNameDic, XrefSymTabTypeNum xrefSymTabTypeNum = XrefSymTabTypeNum.LayerTable) { var workingDb = HostApplicationServices.WorkingDatabase;//数据库转换 HostApplicationServices.WorkingDatabase = db;//数据库转换 db.ResolveXrefs(false, false);//解析数据库 Dictionary<Handle, string> isNestedNodeName = isNestedNodeNameDic;//要处理的嵌套参照的数据字典 var bindXrefsIds = new ObjectIdCollection();//声明要BindXrefs的集合 var xBindXrefsIds = new ObjectIdCollection();//声明要XBindXrefs的集合 var isNestedIds = new ObjectIdCollection();//要处理的嵌套参照ObjectId集合 using (var tr = db.TransactionManager.StartTransaction()) { #region 原块表参照的id集合获取 var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);//块表 foreach (ObjectId id in bt) { var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead); if (btr.IsFromExternalReference && btr.IsResolved) bindXrefsIds.Add(id); } #endregion #region 补充是否被嵌套卸载的处理 XrefGraph xg = db.GetHostDwgXrefGraph(true); int xrefcount = xg.NumNodes; for (int j = 0; j < xrefcount; j++) { XrefGraphNode xrNode = xg.GetXrefNode(j); if (xrNode.XrefStatus == XrefStatus.Unloaded)//若文件已卸载 { ObjectId deTachId = xrNode.BlockTableRecordId; BlockTableRecord btr = (BlockTableRecord)tr.GetObject(deTachId, OpenMode.ForRead); if (btr.IsFromExternalReference) { if (!xrNode.IsNested)//若为非嵌套参照 { db.DetachXref(deTachId);//拆离已经卸载的非嵌套文件 } else //若为嵌套参照 { isNestedIds.Add(deTachId); isNestedNodeName.Add(deTachId.Handle, xrNode.Name);//有嵌套参照,添加关键信息进字典,以传出方法供绑定后删除处理 } } } if (xrNode.XrefStatus == XrefStatus.Unreferenced)//若文件未参照 { db.DetachXref(xrNode.BlockTableRecordId);//拆离未参照的文件 } #region 使用此方法添加的xrNode.BlockTableRecordId,绑定中会随机出现异常(勿用) //if (xrNode.XrefStatus == XrefStatus.Resolved)//若文件已解析 //{ // ObjectId bindXrefId = xrNode.BlockTableRecordId; // BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bindXrefId, OpenMode.ForRead); // if (btr.IsFromExternalReference) // { // xrefIds.Add(bindXrefId); // } //} #endregion } #endregion #region 添加XBindXrefs符号表记录id。根据symbolTableRecordNum值范围0~4动态控制5个符号表记录累加绑定需求 int symbolTableRecordNum = 0; switch (xrefSymTabTypeNum) { case XrefSymTabTypeNum.LayerTable: symbolTableRecordNum = 0; break; case XrefSymTabTypeNum.TextStyleTable: symbolTableRecordNum = 1; break; case XrefSymTabTypeNum.DimStyleTable: symbolTableRecordNum = 2; break; case XrefSymTabTypeNum.LinetypeTable: symbolTableRecordNum = 3; break; case XrefSymTabTypeNum.RegAppTable: symbolTableRecordNum = 4; break; } if (symbolTableRecordNum >= 0)//为0时被本人称为"无敌绑定"项 { LayerTable layert = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;//图层表 foreach (ObjectId id in layert) { LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead); if (ltr.IsResolved) { xBindXrefsIds.Add(ltr.ObjectId); } } } if (symbolTableRecordNum >= 1) { TextStyleTable textstylet = tr.GetObject(db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable;//文字样式表 foreach (ObjectId id1 in textstylet) { TextStyleTableRecord textstyletr = (TextStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (textstyletr.IsResolved) { xBindXrefsIds.Add(textstyletr.ObjectId); } } } if (symbolTableRecordNum >= 2) { LinetypeTable linetypet = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;//线型表 foreach (ObjectId id1 in linetypet) { LinetypeTableRecord linetr = (LinetypeTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (linetr.IsResolved) { xBindXrefsIds.Add(linetr.ObjectId); } } } if (symbolTableRecordNum >= 3) { DimStyleTable dimt = tr.GetObject(db.DimStyleTableId, OpenMode.ForRead) as DimStyleTable;//标注样式表 foreach (ObjectId id1 in dimt) { DimStyleTableRecord dtr = (DimStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (dtr.IsResolved) { xBindXrefsIds.Add(dtr.ObjectId); } } } if (symbolTableRecordNum >= 4) { RegAppTable regappt = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;//注册应用程序表 foreach (ObjectId id1 in regappt) { RegAppTableRecord regapptr = (RegAppTableRecord)tr.GetObject(id1, OpenMode.ForRead); if (regapptr.IsResolved) { xBindXrefsIds.Add(regapptr.ObjectId); } } } #region 起初测试是将9大符号表记录均加入的,但经实测不行。所以根据截取帮助文件中描述,仅添加了块表外的5表记录id ///xrefSymbolIds可能包含以下符号表记录类型的 ObjectId: ///BlockTableRecord、LayerTableRecord、LinetypeTableRecord、TextStyleTableRecord(如果它不代表形状文件)、RegAppTableRecord和DimStyleTableRecord。 //ViewportTable viewport = tr.GetObject(db.ViewportTableId, OpenMode.ForRead) as ViewportTable;//视口表 //foreach (ObjectId id1 in viewport) //{ // ViewportTableRecord viewportr = (ViewportTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (viewportr.IsResolved) // { // xrefIds1.Add(viewportr.ObjectId); // } //} //ViewTable viewt = tr.GetObject(db.ViewTableId, OpenMode.ForRead) as ViewTable;// 视图表 //foreach (ObjectId id1 in viewt) //{ // ViewTableRecord viewtr = (ViewTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (viewtr.IsResolved) // { // xrefIds1.Add(viewtr.ObjectId); // } //} //UcsTable ucst = tr.GetObject(db.UcsTableId, OpenMode.ForRead) as UcsTable;// 用户坐标系表 //foreach (ObjectId id1 in ucst) //{ // UcsTableRecord ucstr = (UcsTableRecord)tr.GetObject(id1, OpenMode.ForRead); // if (ucstr.IsResolved) // { // xrefIds1.Add(ucstr.ObjectId); // } //} #endregion #endregion } if (isNestedIds.Count > 0)//若有嵌套参照被卸载,重载 { db.ReloadXrefs(isNestedIds); } #region 此处即为二者结合使用,且顺序非常重要。若交换秩序,则会绑定无效,切勿交换 db.XBindXrefs(xBindXrefsIds, true);//建议为true db.BindXrefs(bindXrefsIds, true);//建议为true #endregion isNestedNodeNameDic = isNestedNodeName; HostApplicationServices.WorkingDatabase = workingDb; } /// <summary> /// 清理符号7表(块表,标注样式表,图层表,线型表,文字样式表,视口样式表,注册应用表) ///注:视图样式表和坐标系表不能这样清理,有异常 /// </summary> /// <param name="db">数据库</param> /// <returns>无返回值</returns> public static void Purge(Database db) { ObjectIdCollection ids; ObjectIdCollection ids1; ObjectIdCollection ids2; ObjectIdCollection ids3; ObjectIdCollection ids4; ObjectIdCollection ids5; //ObjectIdCollection ids6; //ObjectIdCollection ids7; ObjectIdCollection ids8; using (Transaction tr = db.TransactionManager.StartTransaction()) { //块表 BlockTable blockt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; //标注样式表1 DimStyleTable dimt = tr.GetObject(db.DimStyleTableId, OpenMode.ForRead) as DimStyleTable; //图层表2 LayerTable layert = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable; //线型表3 LinetypeTable linetypet = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable; //文字样式4 TextStyleTable textstylet = tr.GetObject(db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable; //视口样式表5 ViewportTable viewport = tr.GetObject(db.ViewportTableId, OpenMode.ForRead) as ViewportTable; //注册应用表8 RegAppTable regappt = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable; #region 开始清理 do { ids = new ObjectIdCollection(blockt.Cast<ObjectId>().ToArray()); db.Purge(ids); if (ids != null) { foreach (ObjectId id in ids) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } ids1 = new ObjectIdCollection(dimt.Cast<ObjectId>().ToArray()); db.Purge(ids1); if (ids1 != null) { foreach (ObjectId id in ids1) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } ids2 = new ObjectIdCollection(layert.Cast<ObjectId>().ToArray()); db.Purge(ids2); if (ids2 != null) { foreach (ObjectId id in ids2) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } ids3 = new ObjectIdCollection(linetypet.Cast<ObjectId>().ToArray()); db.Purge(ids3); if (ids3 != null) { foreach (ObjectId id in ids3) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } ids4 = new ObjectIdCollection(textstylet.Cast<ObjectId>().ToArray()); db.Purge(ids4); if (ids4 != null) { foreach (ObjectId id in ids4) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } ids5 = new ObjectIdCollection(viewport.Cast<ObjectId>().ToArray()); db.Purge(ids5); if (ids5 != null) { foreach (ObjectId id in ids5) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } #region 经测试视图样式表和坐标系表不能这样清理,不然有异常 ////视图样式表6 //ViewTable viewt = tr.GetObject(db.ViewTableId, OpenMode.ForRead) as ViewTable; //ids6 = new ObjectIdCollection(viewt.Cast<ObjectId>().ToArray()); //db.Purge(ids6); //foreach (ObjectId id in ids6) //{ // ViewTableRecord btr6 = (ViewTableRecord)tr.GetObject(id, OpenMode.ForWrite); // btr6.Erase(); //} ////坐标系表7 //UcsTable ucst = tr.GetObject(db.UcsTableId, OpenMode.ForRead) as UcsTable; //ids7 = new ObjectIdCollection(ucst.Cast<ObjectId>().ToArray()); //db.Purge(ids7); //foreach (ObjectId id in ids7) //{ // UcsTableRecord btr7 = (UcsTableRecord)tr.GetObject(id, OpenMode.ForWrite); // btr7.Erase(); //} #endregion ids8 = new ObjectIdCollection(regappt.Cast<ObjectId>().ToArray()); db.Purge(ids8); if (ids8 != null) { foreach (ObjectId id in ids8) { tr.GetObject(id, OpenMode.ForWrite).Erase(); } } } while (ids.Count > 0 || ids1.Count > 0 || ids2.Count > 0 || ids3.Count > 0 || ids4.Count > 0 || ids5.Count > 0 || ids8.Count > 0); #endregion tr.Commit();//提交事务 } } }
后续3:
20220822-关于多开CAD后台批量绑定的bug解释,如下图
情况1:先开CAD被卡死情况
情况2:多开CAD同步绑,均能顺利完全绑定
未完待续...
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!