AutoCAD中的扩展字典及扩展记录(C#)

在学习CAD扩展记录的过程中,遇到了一些问题,也积累了一些经验,现在给大家分享一些我的学习心得。在学习扩展字典之前需要读者了解cad的组码,也就是DxfCode。感兴趣的也可以了解一下扩展数据的相关内容(后面有时间也会分享一下,因为扩展数据、扩展字典和DxfCode组码之间有密切的关系)。

一个CAD对象只能拥有一个扩展字典,而扩展字典下面可以包含多个扩展记录。打个比方,可以这么理解,如果扩展字典相当于excel文件,那么一个扩展记录就相当于excel中的一个表单sheet对象,扩展记录中存储的数据就相当于表单sheet中的数据。

使用扩展记录可以向对象中保存一些属性数据,以便后续提取之用,这是很有用的。比如说可以向一个多段线(代表一根管线,或是其他)中存储一些施工方面的数据信息,例如施工标段、桩号范围、施工完成时间等,以后再打开图的时候,就知道这段管线是哪个施工单位施工的,什么时间完成的等等,便于查看和统计。CAD程序自身的属性对话框是无法记录这些信息的。

向对象添加扩展记录一般分为三个步骤:

1 将添加的数据构成一个类

2 编写扩展方法,包括扩展记录的添加、读取、删除、修改

3 调用扩展方法进行操作

界面如下:

 

下面列出主要的代码

1 将需要添加的数据构成一个类,主要包括施工标段、信息、桩号、完成时间等属性

复制代码

 1  public class XDataClass
 2     {
 3         public string BiaoDuan { get; set; }//施工标段
 4         public string Information { get; set; }//附加到对象上的信息
 5         public double StationStart { get; set; }//起始桩号
 6         public double StationEnd { get; set; }//终止桩号
 7         public double Length { get; private set; }//长度
 8         public DateTime OverTime { get; set; }//完成时间
 9         public string XRecordName { get; set; } //扩展记录名称
10         public XDataClass() { }
11         public XDataClass(string xrecordName)
12         {
13             XRecordName = xrecordName;
14         }
15         /// <summary>
16         /// 将扩展数据实体类转化成typevaluelist类型
17         /// </summary>
18         /// <param name="xdataClass"></param>
19         /// <returns></returns>
20         public static TypedValueList ClassToTypeValueList(XDataClass xdataClass)
21         {
22             TypedValueList tvList = new TypedValueList
23             {
24                 {DxfCode.Text, xdataClass.BiaoDuan },
25                 {DxfCode.Text, xdataClass.Information },
26                 {DxfCode .Real ,xdataClass.StationStart  },
27                 {DxfCode.Real ,xdataClass .StationEnd  },
28                 {DxfCode.Text ,xdataClass .OverTime .ToString ("d") },
29                 {DxfCode.Text ,xdataClass.XRecordName  },
30             }; 
31             return tvList;
32         }
33         /// <summary>
34         /// 将typevaluelist类型的数据转换成实体类
35         /// </summary>
36         /// <param name="list"></param>
37         /// <returns></returns>
38         public static XDataClass TypeValueListToClass(TypedValueList list)
39         {
40             XDataClass xdataClass = new XDataClass()
41             {
42                 BiaoDuan = list[0].Value.ToString(),
43                 Information = list[1].Value.ToString(),
44                 StationStart = Convert.ToDouble(list[2].Value),
45                 StationEnd = Convert.ToDouble(list[3].Value),
46                 OverTime = Convert.ToDateTime(list[4].Value),
47                 XRecordName = list[5].Value.ToString(),
48                 Length = Math.Abs(Convert.ToDouble(list[3].Value) - Convert.ToDouble(list[2].Value))
49             };
50             return xdataClass;
51         }
52     }

复制代码

 

2  编写扩展方法,包括扩展记录的添加、读取、删除、修改

复制代码

  1 #region 对象的扩展记录的添加、删除、修改
  2         /// <summary>
  3         ///  添加扩展记录,如果没有扩展字典,那就创建扩展字典
  4         /// </summary>
  5         /// <param name="objId">对象的objectid</param>
  6         /// <param name="xRecordSearchKey">扩展记录名称</param>
  7         /// <param name="values">扩展记录的内容</param>
  8         /// <returns></returns>
  9         public static bool AddXRecordToObj(this ObjectId objId, string xRecordSearchKey, TypedValueList values)
 10         {
 11             //添加扩展记录之前,先创建对象的扩展字典
 12             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开
 13             if (obj.ExtensionDictionary.IsNull)//如果对象无扩展字典,那就给创建
 14             {
 15                 obj.UpgradeOpen();//切换对象为写的状态
 16                 obj.CreateExtensionDictionary();//为对象创建扩展字典,一个对象只能拥有一个扩展字典
 17                 obj.DowngradeOpen();//将对象切换为读的状态
 18             }
 19             //打开对象的扩展字典
 20             DBDictionary dict = obj.ExtensionDictionary.GetObject(OpenMode.ForRead) as DBDictionary;
 21             //如果扩展字典中已包含指定的扩展记录对象  
 22             if (dict.Contains(xRecordSearchKey))
 23             {
 24                  return false;//如果包含有指定的扩展记录,那就退出
 25             }
 26             else //若没有包含扩展记录,则创建一个
 27             {
 28                 Xrecord xrec = new Xrecord();//为对象创建一个扩展记录 
 29                 xrec.Data = values;//指定扩展记录的内容,这里用到了自定义类型转换,TypedValueList-->ResultBuffer
 30                 dict.UpgradeOpen();//将扩展字典切换为写的状态,以便添加一个扩展记录
 31                 ObjectId xrecId = dict.SetAt(xRecordSearchKey, xrec);//在扩展字典中加入新建的扩展记录,并指定它的搜索关键字
 32                 objId.Database.TransactionManager.AddNewlyCreatedDBObject(xrec, true);
 33                 dict.DowngradeOpen();//将扩展字典切换为读的状态
 34                 return true; 
 35             }
 36         }
 37 
 38         /// <summary>
 39         /// 用于替换扩展字典中的整个一条扩展记录
 40         /// </summary>
 41         /// <param name="objId">对象id</param>
 42         /// <param name="xRecordSearchKey">扩展记录的名称</param>
 43         /// <param name="values">扩展记录的内容</param>
 44         public static bool ModObjXrecord(this ObjectId objId, string xRecordSearchKey, TypedValueList values)
 45         {
 46             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
 47             ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
 48             if (dictId.IsNull)
 49             {
 50                 return false;//若对象没有扩展字典,则返回 
 51             }
 52             //如果对象有扩展字典,则以读的方式打开
 53             DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;
 54             if (!dict.Contains(xRecordSearchKey))
 55             {
 56                 return false;//如果扩展字典中没有包含指定关键字的扩展记录,则返回 ;
 57             }
 58             ObjectId xrecordId = dict.GetAt(xRecordSearchKey);//获取扩展记录的id
 59             Xrecord xrecord = xrecordId.GetObject(OpenMode.ForWrite) as Xrecord;
 60             xrecord.Data = values;//覆盖原来的数据,因为values有了新的指向
 61             xrecord.DowngradeOpen();//将扩展记录切换为读的状态
 62             return true;
 63         }
 64 
 65         /// <summary>
 66         /// 获取对象的扩展字典中的扩展记录
 67         /// </summary>
 68         /// <param name="objId">对象的id</param>
 69         /// <param name="xRecordSearchKey">扩展记录名称</param>
 70         /// <returns></returns>
 71         public static TypedValueList GetObjXrecord(this ObjectId objId, string xRecordSearchKey)
 72         {
 73             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
 74             ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典的id
 75             if (dictId.IsNull)
 76             {
 77                 //MessageBox.Show("没有扩展字典");
 78                 return null;//若对象没有扩展字典,则返回null
 79             }
 80             DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;//获取对象的扩展字典
 81             if (!dict.Contains(xRecordSearchKey))
 82             {
 83                 return null;//如果扩展字典中没有包含指定关键字的扩展记录,则返回null;
 84             }
 85             //先要获取对象的扩展字典或图形中的有名对象字典,然后才能在字典中获取要查询的扩展记录
 86             ObjectId xrecordId = dict.GetAt(xRecordSearchKey);//获取扩展记录对象的id
 87             Xrecord xrecord = xrecordId.GetObject(OpenMode.ForRead) as Xrecord;//根据id获取扩展记录对象
 88             TypedValueList values = xrecord.Data;
 89             return values;//values 数组应该是有先后顺序的
 90         }
 91 
 92         /// <summary>
 93         ///用于删除对象扩展字典中的指定的扩展记录
 94         /// </summary>
 95         /// <param name="objId">对象id</param>
 96         /// <param name="xRecordSearchKey"> 扩展记录名称</param>
 97         public static bool DelObjXrecord(this ObjectId objId, string xRecordSearchKey)
 98         {
 99             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
100             ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
101             if (dictId.IsNull)
102             {
103                 return false;//若对象没有扩展字典,则返回 
104             }
105             //如果对象有扩展字典,则以读的方式打开
106             DBDictionary dict = dictId.GetObject(OpenMode.ForRead) as DBDictionary;
107             if (dict.Contains(xRecordSearchKey))//如果扩展字典中包含指定关键字的扩展记录,则删除;
108             {
109                 dict.UpgradeOpen();//切换为写的状态
110                 dict.Remove(xRecordSearchKey);//删除扩展记录
111                 dict.DowngradeOpen();//切换为读的状态
112             }
113             return true;
114         }
115         
116         /// <summary>
117         /// 删除对象的扩展字典下的所有的扩展记录
118         /// 2018年4月7日09:44:12
119         /// </summary>
120         /// <param name="objId"></param>
121         public static bool DelObjAllXrecords(this ObjectId objId)
122         {
123             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
124             ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典id
125             if (dictId.IsNull)
126             {
127                 return false;//若对象没有扩展字典,则返回 
128             }
129             //如果对象有扩展字典,则以读的方式打开
130             DBDictionary dict = dictId.GetObject(OpenMode.ForWrite) as DBDictionary;
131             //获取扩展字典下的所有扩展记录名称集合 Keys 
132 133             List<string> listKeys = new List<string>();
134             foreach (var item in dict)//获取扩展字典中的所有条目,也就是所有的扩展记录的key
135             {
136                 listKeys.Add(item.Key);
137             }
138             foreach (var key in listKeys)//根据key,删除扩展字典中的每一个条目(也就是扩展记录)
139             {
140                 dict.Remove(key);
141             }
142             dict.DowngradeOpen();//切换为读的状态 
143             return true;
144         }
145 
146 
147         /// <summary>
148         /// 删除对象的扩展字典,因为每个对象只能拥有一个扩展字典,所以给定对象的objectID就好了
149         ///  2018年4月7日09:17:44 
150         /// </summary>
151         /// <param name="objId"></param>
152         public static bool DeleteObjExtensionDictionary(this ObjectId objId)
153         {
154             DBObject obj = objId.GetObject(OpenMode.ForRead);//以读的方式打开对象
155             ObjectId dictId = obj.ExtensionDictionary;//获取对象的扩展字典的ID
156             if (dictId.IsNull)
157             {
158                 return false;    //没有扩展字典
159             }
160             //有扩展字典 161             obj.UpgradeOpen();//切换对象为写的状态
162             objId.DelObjAllXrecords(); //调用上面的方法,在删除扩展字典之前要先删除扩展记录
163             obj.ReleaseExtensionDictionary();//移除对象的扩展字典,一个对象只能拥有一个扩展字典
164             obj.DowngradeOpen();//将对象切换为读的状态 
165             return true;
166         }
167         #endregion

复制代码

 

3调用扩展方法

  a 添加扩展记录

复制代码

 1  //btn  添加扩展记录
 2         XDataClass PipeXdataClass = new XDataClass(Enum_XRcordName.pipe_whlkx.ToString());
 3         ObjectId selectedObjId = ObjectId.Null;
 4         private void btnAddXData_Click(object sender, EventArgs e)
 5         {
 6             if (CheckValue() == false)
 7             {
 8                 return;
 9             }
10             _instance.Hide();
11             Document doc = AcadApp.DocumentManager.MdiActiveDocument;
12             Database db = doc.Database;
13             Editor ed = doc.Editor; 
14             PromptEntityResult entityResult = ed.GetEntity("\n请选择一个多段线对象");//单个拾取对象 
15             if (entityResult.Status != PromptStatus.OK)
16             {
17                 _instance.Show();
18                 return;
19             }
20             GetDataFromControls(PipeXdataClass);//私有函数,将控件中的数据填充到实体类中
21             //获取对象的ID
22             ObjectId objId = entityResult.ObjectId; 
23             bool result = false;
24             using (DocumentLock docLock = doc.LockDocument())
25             using (Transaction trans = db.TransactionManager.StartTransaction())
26             {
27                 //将xdataCalss类型的数据转换成一个typevalue型的列表
28                 TypedValueList values = XDataClass.ClassToTypeValueList(PipeXdataClass);
29                 result = objId.AddXRecordToObj(PipeXdataClass.XRecordName, values);
30                 trans.Commit();
31             }
32             if (result)
33             {
34                 ed.WriteMessage("\n对象的扩展数据添加成功!");
35             }
36             else
37             {
38                 ed.WriteMessage("\n对象已经有扩展数据");
39             }
40             _instance.Show();
41         }

复制代码

  

  b 读取扩展记录 

复制代码

 1 //btn 读取扩展记录
 2         private void btnReadXData_Click(object sender, EventArgs e)
 3         {
 4             _instance.Hide();
 5             ClearContent();//清空控件中的内容
 6             Document doc = AcadApp.DocumentManager.MdiActiveDocument;
 7             Database db = doc.Database;
 8             Editor ed = doc.Editor;
 9             //开始事务处理
10             using (DocumentLock docLock = doc.LockDocument())
11             using (Transaction trans = db.TransactionManager.StartTransaction())
12             {
13                 PromptEntityResult entityResult = ed.GetEntity("\n请选择一个对象");//拾取单个对象
14                 if (entityResult.Status != PromptStatus.OK)
15                 {
16                     ed.WriteMessage("\n取消了选择");
17                     _instance.Show();
18                     return;
19                 }
20                 //获取对象的ID
21                 ObjectId objId = entityResult.ObjectId;
22                 TypedValueList list = objId.GetObjXrecord(PipeXdataClass.XRecordName);
23                 if (list is null)
24                 {
25                     ed.WriteMessage("\n该对象没有扩展记录");
26                     _instance.Show();
27                     return;
28                 }
29                 if (list.Count <= 0)
30                 {
31                     ed.WriteMessage("\n有扩展记录,但是记录为空");
32                     _instance.Show();
33                     return;
34                 }
35                 else
36                 {
37                     PipeXdataClass = XDataClass.TypeValueListToClass(list);
38                     SetDataToControls(PipeXdataClass);//向控件中填充数据
39                     ed.WriteMessage("\n对象扩展数据读取成功");
40                     selectedObjId = objId;
41                 }
42             }
43             _instance.Show();
44         }

复制代码

 

  c 删除扩展记录

复制代码

 1         //btn 删除
 2         private void btnDeleteXData_Click(object sender, EventArgs e)
 3         {
 4             _instance.Hide();
 5             Document doc = AcadApp.DocumentManager.MdiActiveDocument;
 6             Database db = doc.Database;
 7             Editor ed = doc.Editor;
 8             //开始事务处理
 9             using (DocumentLock docLock = doc.LockDocument())
10             using (Transaction trans = db.TransactionManager.StartTransaction())
11             {
14                 PromptSelectionResult ss1 = ed.GetSelection();//框选对象
15                 if (ss1.Status != PromptStatus.OK)
16                 {
17                     ed.WriteMessage("\n取消了选择");
18                     _instance.Show();
19                     return;
20                 }
21                 //获取对象的ID
22                 List<ObjectId> listObjIds = ss1.Value.GetObjectIds().ToList();
23                 int count = 0;
24                 listObjIds.ForEach(objId =>
25                 {
26                     if (objId.DeleteObjExtensionDictionary())
27                     {
28                         ed.WriteMessage("\n删除成功");
29                         count++;
30                     }
31                 });
32                 //ObjectId objId = entityResult.ObjectId;
33                 //2018年4月7日09:50:35,经验证,必须先删除扩展字典下的所有的扩展记录,才能删除对象的扩展字典
34                 //否则会出现错误:eContainerNotEmpty ,容器不为空
35                 //objId.DelObjAllXrecords();
36                 //objId.DeleteObjExtensionDictionary();
37                 trans.Commit();
38                 ed.WriteMessage("\n操作完成,总共删除{0}个扩展记录", count);
39             } 
40             _instance.Show();
41         }

复制代码

 修改扩展记录可以自己写一下,比较简单。

  下面给出一张图关于扩展字典和扩展记录的示意图,便于理解之间的关系。

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值