一.簡述
CAD數據庫對象可以靈活添加一定數量的自定義數據,供開發者使用,這些數據由開發者自己進行解釋 ,CAD不管其含義,但要遵循一定的組碼規則,這些數據被稱為擴展數據XData。擴展數據以吸附物的形式吸附在實體上。
1.可以通過實體DBObject類及其派生類的XData屬性獲取或設置擴展數據,實體的擴展數據由應用程序創建。
2.實體的擴展數據可以是一組或多組,每一組都以一個互不相同的注冊應用程序名開頭。
簡而蓋之:
XData數據形式類似字典Dictionary,但是此字典的key有一個,value可以是多個(一組或多組),這里的key必須按照DxfCode組碼規則來,value也必須根據選定的組碼選用約定好的數據形式
DXF 組碼值 |
擴展數據內容 |
1000~1009 |
字符串 (最多不超過 255 個字符) |
1001 |
Xdata 的應用程序名 |
1002 |
Xdata 的控制字符串 |
1003 |
圖層名 |
1004 |
二進制數據 |
1005 |
數據庫對象句柄 |
1010~1059 |
浮點數 |
1010,1020,1030 |
三維點(x, y , z) |
1011,1021,1031 |
三維空間位置 |
1012,1022,1032 |
三維空間距離 |
1013,1023,1033 |
三維空間方向 |
1040 |
Xdata 中的浮點數 |
1041 |
Xdata 中的距離值 |
1042 |
Xdata 中的比例系數 |
1060~1070 |
16 位整數 |
1071 |
32 位整數 |
二.步驟
1.注冊應用程序
什么是應用程序---->說白了就相當於你擴展數據的一個分類,擴展數據前,必須明確你擴展的數據屬於哪一個應用程序。
2.注冊應用程序
應用程序首先應要注冊到CADRegAppTable表中,在給圖元擴展數據的時候,首先明確擴展數據對應的應用程序是否已經注冊,沒有注冊的則必須注冊。CAD將注冊的應用程序名保存於數據庫中的RegAppTable中。使用之前應檢測應用程序名是否已經注冊,如果沒有注冊,則需要創建一個RegAppTableRecord表記錄。
3.數據對
結果緩存即 Autodesk.AutoCAD.DatabaseServices.ResultBuffer 類型,使用 ResultBuffer 對象時需要提供一個數據對,每個數據對包含一個數據類型描述和一個值,這些數據對Autodesk.AutoCAD.DatabaseServices.TypedValue 類的實例。
TypedValue.TypeCode 屬性是一個16位整型數據,它指明 TypedValue.Value 屬性的數據類型,可接受的 TypeCode 值取決於 ResultBuffer 實例的使用范圍。
例如,適用於擴展記錄定義的 TypeCode 值就不適合於 XData。而Autodesk.AutoCAD.DatabaseServices.DxfCode 枚舉類型定義的碼值則描述了 ResultBuffer 可能的數據類型。
TypedValue.Value 屬性是一個 System.Object 的實例,它可以包含任何類型的數據;但是,Value 的數據必須符合由 TypeCode 指明的類型。
創建 ResultBuffer 方法有兩種:
1.一種是使用構造函數創建,即在聲明 ResultBuffer 時將一個 TypedValue 作用參數傳給 ResultBuffer:
2.另一種是使用 ResultBuffer.Add() 方法來添加 TypedValue,可以添加多個TypedValue,但總數據大小不能超過128K:
ResultBuffer resBuf = new ResultBuffer();
resBuf.Add(new TypedValue(1001, "appname")); //必須放在第一條添加,否則會報錯
resBuf.Add(new TypedValue(1000, "作者:王"));
注意// resBuf 必須包含 1001 對應的值 就是應用程序名稱
ResultBuffer resBuf = new ResultBuffer(new TypedValue((int)DxfCode.Text, "我的擴展數據"));
但是這里雖然是用等號賦值的,但是它並不一定會覆蓋舊的擴展數據,一個實體,只有一個XData屬性,但是里面可以記錄多個不同應用程序名的擴展數據。
每次用“=”給實體的XData賦值時,如果XData里還沒有這個應用程序的擴展數據,那么新賦的這些值,會被添加到原有的XData結尾去。
三.代碼
通用代碼:

/// <summary> /// 給指定的實體增加擴展數據 根據 DBObject /// </summary> /// <param name="db">db</param> /// <param name="obj">ent等</param> /// <param name="regAppName">擴展數據名</param> /// <param name="tv">擴展數據</param> public static void SetXData(Database db, DBObject obj, string regAppName, TypedValue[] tv) { using (Transaction tr = db.TransactionManager.StartTransaction()) { RegAppTable rat = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForWrite); using (ResultBuffer rb = new ResultBuffer(tv)) { obj.UpgradeOpen(); CheckAddAppName(tr, rat, regAppName); //注冊並添加擴展數據名 obj.XData = rb; rb.Dispose(); tr.Commit(); } } }

/// <summary> /// 注冊並添加擴展數據名 /// </summary> /// <param name="regAppName"></param> public static void CheckAddAppName(Transaction tr, RegAppTable rat, string regAppName) { if (!rat.Has(regAppName)) { RegAppTableRecord ratr = new RegAppTableRecord(); ratr.Name = regAppName; rat.Add(ratr); tr.AddNewlyCreatedDBObject(ratr, true); } }

/// <summary> /// 得到擴展數據 /// </summary> /// <param name="db">db</param> /// <param name="entId">實體Id</param> /// <param name="regAppName">擴展數據名</param> /// <param name="tv">擴展數據</param> /// <returns>true,false</returns> public static bool TryGetXData(Database db, ObjectId entId, string regAppName, out TypedValue[] tv) { Transaction tr = db.TransactionManager.StartTransaction(); using (tr) { DBObject obj = tr.GetObject(entId, OpenMode.ForRead); using (ResultBuffer rb = obj.GetXDataForApplication(regAppName)) { if (rb != null) { tv = rb.AsArray(); return true; } else { tv = null; return false; } } } }
四.總結
1.每一條擴展數據都必須以應用程序名開頭。
2. XData數據形式類似字典Dictionary,但是此字典的key有一個,value可以是多個(一組或多組),這里的key必須按照DxfCode組碼規則來,value也必須根據選定的組碼選用約定好的數據形式。
3.一個實體可以有多個擴展數據,只要應用程序名不同即可(-3 ("firstapp" (1000 . "測試") (1040 . 800.0)) ("firstapp2" (1000 . "測試") (1040 . 800.0))))
注意:在項目開發中,CAD程序文件有可能被殺毒軟件誤殺掉擴展數據相關文件,建議少用XData,可以用Xrecord,其次XData數據的形式約束和長度約束也不是很便利。
版權提醒:
本人辛苦總結的文章最近被http://www.bubuko.com/網站原封不動的抄襲,請問你的良心何在,至少也要說一聲轉發吧,本人保留法律追究權利。
如果要轉發本人文章,請標注轉發字眼,尊重原創。