CAD.NET中使用XBindXrefs、BindXrefs双重绑定参照的探讨

打印 上一主题 下一主题

主题 868|帖子 868|积分 2604

/* CAD2023在线帮助链接 https://help.autodesk.com/view/OARX/2023/ENU/?guid=OARX-ManagedRefGuide-Autodesk_AutoCAD_DatabaseServices_Database_XBindXrefs_ObjectIdCollection__MarshalAsUnmanagedType_U1__bool
   
* (注:本文仅为自己在实际工作中遇到的问题,所找到的一种解决方案,仅供参考、学习使用。若有不足处,欢迎在评论区留言纠正)
    *   一、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个符号表记录,一一单选绑定,本人未进行测试,所需者可根据自身要求测试绑定效果。
    *   
    *   五、附本人测试成功的封装代码。如有引用本文,请标识出处。
    */
  1. using Autodesk.AutoCAD.DatabaseServices;
  2. using System.Collections.Generic;
  3. using AcCoreAp = Autodesk.AutoCAD.ApplicationServices.Core.Application;<br>namespace Oncet.CAD
  4. {
  5.     public static class XrefEx
  6.     {
  7.         /// <summary>
  8.         /// XBindXrefs、BindXrefs双重绑定参照。增加绑定符号表累计的选择;增加储存嵌套参照被卸载的字典ref方式
  9.         /// </summary>
  10.         /// <param name="db">数据库</param>
  11.         /// <param name="symbolTableRecordNum">累计要绑定的符号表数量,默认为0。最小为0,最大为4。具体【0为"图层表",1为"文字样式表",2为"线型表",3为"注册应用程序表",4为"标注样式表"】</param>
  12.         /// <param name="isNestedNodeNameDic">储存嵌套参照被卸载的字典</param>
  13.         public static void XBindXrefs(Database db, ref Dictionary<Handle, string> isNestedNodeNameDic, int symbolTableRecordNum = 0)
  14.         {//数据库转换
  15.             var workingDb = HostApplicationServices.WorkingDatabase;
  16.             HostApplicationServices.WorkingDatabase = db;
  17.             string errorRemark = db.OriginalFileName;//标记可能出错的文件名,在异常时使用;
  18.             Dictionary<Handle, string> isNestedNodeName = isNestedNodeNameDic;
  19.             try
  20.             {
  21.                 db.ResolveXrefs(false, false);//解析数据库
  22.                 var bindXrefsIds = new ObjectIdCollection();//声明要BindXrefs的集合
  23.                 var xBindXrefsIds = new ObjectIdCollection();//声明要XBindXrefs的集合
  24.                 ObjectIdCollection isNestedIds = new ObjectIdCollection();//20220815
  25.                 using (var tr = db.TransactionManager.StartTransaction())
  26.                 {
  27.                     #region MyRegion20220815-批注原块表参照的id集合获取
  28.                     var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);//块表
  29.                     foreach (ObjectId id in bt)
  30.                     {
  31.                         var btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
  32.                         if (btr.IsFromExternalReference && btr.IsResolved)
  33.                             bindXrefsIds.Add(id);
  34.                     }
  35.                     #endregion
  36.                     #region MyRegion20220815补充是否被嵌套卸载的处理
  37.                     XrefGraph xg = db.GetHostDwgXrefGraph(true);
  38.                     int xrefcount = xg.NumNodes;
  39.                     for (int j = 0; j < xrefcount; j++)
  40.                     {
  41.                         XrefGraphNode xrNode = xg.GetXrefNode(j);
  42.                         if (xrNode.XrefStatus == XrefStatus.Unloaded)//若文件已卸载
  43.                         {
  44.                             ObjectId deTachId = xrNode.BlockTableRecordId;
  45.                             BlockTableRecord btr = (BlockTableRecord)tr.GetObject(deTachId, OpenMode.ForRead);
  46.                             if (btr.IsFromExternalReference)
  47.                             {
  48.                                 if (!xrNode.IsNested)//若为非嵌套参照
  49.                                 {
  50.                                     db.DetachXref(deTachId);//拆离已经卸载的非嵌套文件
  51.                                 }
  52.                                 if (xrNode.IsNested)//若为嵌套参照
  53.                                 {
  54.                                     isNestedIds.Add(deTachId);
  55.                                     isNestedNodeName.Add(deTachId.Handle, xrNode.Name);//有嵌套参照,添加关键信息进字典,以传出方法供绑定后删除处理
  56.                                 }
  57.                             }
  58.                         }
  59.                         if (xrNode.XrefStatus == XrefStatus.Unreferenced)//若文件未参照
  60.                         {
  61.                             db.DetachXref(xrNode.BlockTableRecordId);//拆离未参照的文件
  62.                         }
  63.                         #region MyRegion使用此方法添加的xrNode.BlockTableRecordId,绑定中会随机出现异常(勿用)
  64.                         //if (xrNode.XrefStatus == XrefStatus.Resolved)//若文件已解析
  65.                         //{
  66.                         //    ObjectId bindXrefId = xrNode.BlockTableRecordId;
  67.                         //    BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bindXrefId, OpenMode.ForRead);
  68.                         //    if (btr.IsFromExternalReference)
  69.                         //    {
  70.                         //        xrefIds.Add(bindXrefId);
  71.                         //    }
  72.                         //}
  73.                         #endregion
  74.                     }
  75.                     #endregion
  76.                     #region MyRegion20220814添加XBindXrefs符号表记录id。根据symbolTableRecordNum值范围0~4动态控制5个符号表记录累加绑定需求
  77.                     if (symbolTableRecordNum >= 0)//为0时被本人称为“无敌绑定”项
  78.                     {
  79.                         LayerTable layert = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;//图层表
  80.                         foreach (ObjectId id in layert)
  81.                         {
  82.                             LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(id, OpenMode.ForRead);
  83.                             if (ltr.IsResolved)
  84.                             {
  85.                                 xBindXrefsIds.Add(ltr.ObjectId);
  86.                             }
  87.                         }
  88.                     }
  89.                     if (symbolTableRecordNum >= 1)
  90.                     {
  91.                         TextStyleTable textstylet = tr.GetObject(db.TextStyleTableId, OpenMode.ForRead) as TextStyleTable;//文字样式表
  92.                         foreach (ObjectId id1 in textstylet)
  93.                         {
  94.                             TextStyleTableRecord textstyletr = (TextStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  95.                             if (textstyletr.IsResolved)
  96.                             {
  97.                                 xBindXrefsIds.Add(textstyletr.ObjectId);
  98.                             }
  99.                         }
  100.                     }
  101.                     if (symbolTableRecordNum >= 3)
  102.                     {
  103.                         LinetypeTable linetypet = tr.GetObject(db.LinetypeTableId, OpenMode.ForRead) as LinetypeTable;//线型表
  104.                         foreach (ObjectId id1 in linetypet)
  105.                         {
  106.                             LinetypeTableRecord linetr = (LinetypeTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  107.                             if (linetr.IsResolved)
  108.                             {
  109.                                 xBindXrefsIds.Add(linetr.ObjectId);
  110.                             }
  111.                         }
  112.                     }
  113.                     if (symbolTableRecordNum >= 2)
  114.                     {
  115.                         DimStyleTable dimt = tr.GetObject(db.DimStyleTableId, OpenMode.ForRead) as DimStyleTable;//标注样式表
  116.                         foreach (ObjectId id1 in dimt)
  117.                         {
  118.                             DimStyleTableRecord dtr = (DimStyleTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  119.                             if (dtr.IsResolved)
  120.                             {
  121.                                 xBindXrefsIds.Add(dtr.ObjectId);
  122.                             }
  123.                         }
  124.                     }
  125.                     if (symbolTableRecordNum >= 4)
  126.                     {
  127.                         RegAppTable regappt = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;//注册应用程序表
  128.                         foreach (ObjectId id1 in regappt)
  129.                         {
  130.                             RegAppTableRecord regapptr = (RegAppTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  131.                             if (regapptr.IsResolved)
  132.                             {
  133.                                 xBindXrefsIds.Add(regapptr.ObjectId);
  134.                             }
  135.                         }
  136.                     }
  137.                     #region MyRegion20220814起初测试是将9大符号表记录均加入的,但经实测不行。所以根据截取帮助文件中描述,仅添加了块表外的5表记录id
  138.                     ///xrefSymbolIds可能包含以下符号表记录类型的 ObjectId:
  139.                     ///BlockTableRecord、LayerTableRecord、LinetypeTableRecord、TextStyleTableRecord(如果它不代表形状文件)、RegAppTableRecord和DimStyleTableRecord。
  140.                     ///20220814
  141.                     
  142.                     //ViewportTable viewport = tr.GetObject(db.ViewportTableId, OpenMode.ForRead) as ViewportTable;//视口表
  143.                     //foreach (ObjectId id1 in viewport)
  144.                     //{
  145.                     //    ViewportTableRecord viewportr = (ViewportTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  146.                     //    if (viewportr.IsResolved)
  147.                     //    {
  148.                     //        xrefIds1.Add(viewportr.ObjectId);
  149.                     //    }
  150.                     //}
  151.                     //ViewTable viewt = tr.GetObject(db.ViewTableId, OpenMode.ForRead) as ViewTable;// 视图表
  152.                     //foreach (ObjectId id1 in viewt)
  153.                     //{
  154.                     //    ViewTableRecord viewtr = (ViewTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  155.                     //    if (viewtr.IsResolved)
  156.                     //    {
  157.                     //        xrefIds1.Add(viewtr.ObjectId);
  158.                     //    }
  159.                     //}
  160.                     //UcsTable ucst = tr.GetObject(db.UcsTableId, OpenMode.ForRead) as UcsTable;// 用户坐标系表
  161.                     //foreach (ObjectId id1 in ucst)
  162.                     //{
  163.                     //    UcsTableRecord ucstr = (UcsTableRecord)tr.GetObject(id1, OpenMode.ForRead);
  164.                     //    if (ucstr.IsResolved)
  165.                     //    {
  166.                     //        xrefIds1.Add(ucstr.ObjectId);
  167.                     //    }
  168.                     //}
  169.                     #endregion
  170.                     #endregion
  171.                 }
  172.                 if (isNestedIds.Count > 0)//若有嵌套参照被卸载,重载
  173.                 {
  174.                     db.ReloadXrefs(isNestedIds);
  175.                 }
  176.                 #region MyRegion20220814此处即为二者结合使用,且顺序非常重要。若交换秩序,则会绑定无效,切勿交换!!!
  177.                 db.XBindXrefs(xBindXrefsIds, true);//20220814建议为true
  178.                 db.BindXrefs(bindXrefsIds, true);//20220814建议为true
  179.                 #endregion
  180.             }
  181.             catch (System.Exception ex)
  182.             {<br>          throw new System.Exception(ex.Message);<br><em id="__mceDel">          //AcCoreAp.ShowAlertDialog("Error: " + ex.Message); <br><em id="__mceDel"><em id="__mceDel">        } <br><em id="__mceDel"><em id="__mceDel">       finally <br>       { <br>         isNestedNodeNameDic = isNestedNodeName;//20220815 <br>         HostApplicationServices.WorkingDatabase = workingDb; <br>       } <br>    } <br>  } <br>}</em></em></em></em></em>
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

飞不高

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表