Autocad C# - 在撤消时,对象 Xdata 变为空
Autocad C# - On Undo, the object Xdata becomes null
这是在 AutoCAD 2016 中
我们遇到了 xdata 在撤消时显示为 null 的问题。我们使用 Xdata 来跟踪自定义 objects/blocks。我们在迁移到 AutoCAD2016 后开始注意到这一点。
我已经包含了一个例子。 运行 命令 DrawRectangleWithXdata 将创建带有一些扩展数据的折线。您可以在创建对象后通过 运行 命令 ShowBlockXdata 检查这一点。
现在运行 Ctrl+Z 撤消 DrawRectangleWithXdata 命令。
在 Database_ObjectErased 事件中,您可以看到 Xdata 为空。
反正我能得到这个吗?
代码如下:
public partial class MainClass : Autodesk.AutoCAD.Runtime.IExtensionApplication
{
/// <summary>
/// Document collection object
/// </summary>
DocumentCollection docCollection = null;
public void Initialize()
{
docCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
docCollection.DocumentCreated += new DocumentCollectionEventHandler(docCollection_DocumentCreated);
}
public void Terminate()
{
}
/// <summary>
/// Executed whenever a new document is created/opened
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void docCollection_DocumentCreated(object sender, DocumentCollectionEventArgs e)
{
try
{
e.Document.Database.ObjectModified += new ObjectEventHandler(Database_ObjectModified);
e.Document.Database.ObjectErased += new ObjectErasedEventHandler(Database_ObjectErased);
e.Document.Database.ObjectAppended += new ObjectEventHandler(Database_ObjectAppended);
}
catch { }
}
private void Database_ObjectModified(object sender, ObjectEventArgs e)
{
object xdata = e.DBObject.XData;
}
private void Database_ObjectErased(object sender, ObjectErasedEventArgs e)
{
object xdata = e.DBObject.XData;
}
private void Database_ObjectAppended(object sender, ObjectEventArgs e)
{
object xdata = e.DBObject.XData;
}
/// <summary>
/// This method registers the Application name for XData
/// </summary>
/// <param name="regAppName">Application name to be registered</param>
public void AddRegAppTableRecord(string regAppName)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
RegAppTable regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead, false);
if (!regAppTable.Has(regAppName))
{
regAppTable.UpgradeOpen();
RegAppTableRecord ratr = new RegAppTableRecord();
ratr.Name = regAppName;
regAppTable.Add(ratr);
tr.AddNewlyCreatedDBObject(ratr, true);
}
tr.Commit();
}
}
[CommandMethod("ShowBlockXdata", CommandFlags.UsePickSet)]
public void ShowBlockXdata()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
var ss = ed.SelectImplied();
if (ss.Status == PromptStatus.OK)
{
using (Transaction tx = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
foreach (ObjectId objId in ss.Value.GetObjectIds())
{
DBObject dbObject = tx.GetObject(objId, OpenMode.ForRead);
ed.WriteMessage(dbObject.XData.ToString());
}
}
}
}
[CommandMethod("DrawRectangleWithXdata")]
public void DrawRectangle()
{
//Polyline rectangle
var p = new Autodesk.AutoCAD.DatabaseServices.Polyline(4);
p.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
p.AddVertexAt(0, new Point2d(10, 0), 0, 0, 0);
p.AddVertexAt(0, new Point2d(0, 10), 0, 0, 0);
p.AddVertexAt(0, new Point2d(10, 10), 0, 0, 0);
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
AddRegAppTableRecord("MY_OBJECT");
List<TypedValue> xdata = new List<TypedValue>();
xdata.Add(new TypedValue(1001, "MY_OBJECT"));
xdata.Add(new TypedValue(1070, 1234));
ResultBuffer resBuffer = new ResultBuffer(xdata.ToArray());
p.XData = resBuffer;
tr.Commit();
}
}
}
我认为对于 UNDO/REDO 您需要跟踪未附加和重新附加的事件。
尝试放置此块:
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
行后:
p.XData = resBuffer;
像这样:
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
AddRegAppTableRecord("MY_OBJECT");
List<TypedValue> xdata = new List<TypedValue>();
xdata.Add(new TypedValue(1001, "MY_OBJECT"));
xdata.Add(new TypedValue(1070, 1234));
ResultBuffer resBuffer = new ResultBuffer(xdata.ToArray());
p.XData = resBuffer;
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
tr.Commit();
这是在 AutoCAD 2016 中
我们遇到了 xdata 在撤消时显示为 null 的问题。我们使用 Xdata 来跟踪自定义 objects/blocks。我们在迁移到 AutoCAD2016 后开始注意到这一点。
我已经包含了一个例子。 运行 命令 DrawRectangleWithXdata 将创建带有一些扩展数据的折线。您可以在创建对象后通过 运行 命令 ShowBlockXdata 检查这一点。
现在运行 Ctrl+Z 撤消 DrawRectangleWithXdata 命令。 在 Database_ObjectErased 事件中,您可以看到 Xdata 为空。 反正我能得到这个吗?
代码如下:
public partial class MainClass : Autodesk.AutoCAD.Runtime.IExtensionApplication
{
/// <summary>
/// Document collection object
/// </summary>
DocumentCollection docCollection = null;
public void Initialize()
{
docCollection = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager;
docCollection.DocumentCreated += new DocumentCollectionEventHandler(docCollection_DocumentCreated);
}
public void Terminate()
{
}
/// <summary>
/// Executed whenever a new document is created/opened
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void docCollection_DocumentCreated(object sender, DocumentCollectionEventArgs e)
{
try
{
e.Document.Database.ObjectModified += new ObjectEventHandler(Database_ObjectModified);
e.Document.Database.ObjectErased += new ObjectErasedEventHandler(Database_ObjectErased);
e.Document.Database.ObjectAppended += new ObjectEventHandler(Database_ObjectAppended);
}
catch { }
}
private void Database_ObjectModified(object sender, ObjectEventArgs e)
{
object xdata = e.DBObject.XData;
}
private void Database_ObjectErased(object sender, ObjectErasedEventArgs e)
{
object xdata = e.DBObject.XData;
}
private void Database_ObjectAppended(object sender, ObjectEventArgs e)
{
object xdata = e.DBObject.XData;
}
/// <summary>
/// This method registers the Application name for XData
/// </summary>
/// <param name="regAppName">Application name to be registered</param>
public void AddRegAppTableRecord(string regAppName)
{
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Database db = doc.Database;
using (Transaction tr = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
RegAppTable regAppTable = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead, false);
if (!regAppTable.Has(regAppName))
{
regAppTable.UpgradeOpen();
RegAppTableRecord ratr = new RegAppTableRecord();
ratr.Name = regAppName;
regAppTable.Add(ratr);
tr.AddNewlyCreatedDBObject(ratr, true);
}
tr.Commit();
}
}
[CommandMethod("ShowBlockXdata", CommandFlags.UsePickSet)]
public void ShowBlockXdata()
{
Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
var ss = ed.SelectImplied();
if (ss.Status == PromptStatus.OK)
{
using (Transaction tx = HostApplicationServices.WorkingDatabase.TransactionManager.StartTransaction())
{
foreach (ObjectId objId in ss.Value.GetObjectIds())
{
DBObject dbObject = tx.GetObject(objId, OpenMode.ForRead);
ed.WriteMessage(dbObject.XData.ToString());
}
}
}
}
[CommandMethod("DrawRectangleWithXdata")]
public void DrawRectangle()
{
//Polyline rectangle
var p = new Autodesk.AutoCAD.DatabaseServices.Polyline(4);
p.AddVertexAt(0, new Point2d(0, 0), 0, 0, 0);
p.AddVertexAt(0, new Point2d(10, 0), 0, 0, 0);
p.AddVertexAt(0, new Point2d(0, 10), 0, 0, 0);
p.AddVertexAt(0, new Point2d(10, 10), 0, 0, 0);
Database db = HostApplicationServices.WorkingDatabase;
Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
Editor ed = doc.Editor;
Transaction tr = db.TransactionManager.StartTransaction();
using (tr)
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
AddRegAppTableRecord("MY_OBJECT");
List<TypedValue> xdata = new List<TypedValue>();
xdata.Add(new TypedValue(1001, "MY_OBJECT"));
xdata.Add(new TypedValue(1070, 1234));
ResultBuffer resBuffer = new ResultBuffer(xdata.ToArray());
p.XData = resBuffer;
tr.Commit();
}
}
}
我认为对于 UNDO/REDO 您需要跟踪未附加和重新附加的事件。
尝试放置此块:
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
行后:
p.XData = resBuffer;
像这样:
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
AddRegAppTableRecord("MY_OBJECT");
List<TypedValue> xdata = new List<TypedValue>();
xdata.Add(new TypedValue(1001, "MY_OBJECT"));
xdata.Add(new TypedValue(1070, 1234));
ResultBuffer resBuffer = new ResultBuffer(xdata.ToArray());
p.XData = resBuffer;
btr.AppendEntity(p);
tr.AddNewlyCreatedDBObject(p, true);
tr.Commit();