Hi,
Here's a simple and 'brute force' method which erases the existing AttributeReferences from the inserted BlockReferences and adds them new ones from the BlockTableRecord AttributeDefinitions.
The SynchronizeAttributes() method is defined as an extension method for the BlockTableRecord type so that it can be called as an instance method of this type.
Example (assuming btr is a BlocTableRecord instance) : btr.SynchronizeAttributes()
C# code
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using AcRx = Autodesk.AutoCAD.Runtime;
namespace AttSyncSample
{
public static class ExtensionMethods
{
public static void SynchronizeAttributes(this BlockTableRecord target)
{
if (target == null)
throw new ArgumentNullException("btr");
Transaction tr = target.Database.TransactionManager.TopTransaction;
if (tr == null)
throw new AcRx.Exception(ErrorStatus.NoActiveTransactions);
RXClass attDefClass = RXClass.GetClass(typeof(AttributeDefinition));
List<AttributeDefinition> attDefs = new List<AttributeDefinition>();
foreach (ObjectId id in target)
{
if (id.ObjectClass == attDefClass)
{
AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
attDefs.Add(attDef);
}
}
foreach (ObjectId id in target.GetBlockReferenceIds(true, false))
{
BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
br.ResetAttributes(attDefs);
}
if (target.IsDynamicBlock)
{
foreach (ObjectId id in target.GetAnonymousBlockIds())
{
BlockTableRecord btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
{
BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForWrite);
br.ResetAttributes(attDefs);
}
}
}
}
private static void ResetAttributes(this BlockReference br, List<AttributeDefinition> attDefs)
{
TransactionManager tm = br.Database.TransactionManager;
Dictionary<string, string> attValues = new Dictionary<string, string>();
foreach (ObjectId id in br.AttributeCollection)
{
if (!id.IsErased)
{
AttributeReference attRef = (AttributeReference)tm.GetObject(id, OpenMode.ForWrite);
attValues.Add(attRef.Tag, attRef.TextString);
attRef.Erase();
}
}
foreach (AttributeDefinition attDef in attDefs)
{
AttributeReference attRef = new AttributeReference();
attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
if (attValues.ContainsKey(attDef.Tag))
{
attRef.TextString = attValues[attDef.Tag.ToUpper()];
}
br.AttributeCollection.AppendAttribute(attRef);
tm.AddNewlyCreatedDBObject(attRef, true);
}
}
}
}
VB code
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Runtime
Module ExtensionMethods
<System.Runtime.CompilerServices.Extension> _
Public Sub SynchronizeAttributes(target As BlockTableRecord)
If target Is Nothing Then
Throw New ArgumentNullException("btr")
End If
Dim tr As Transaction = target.Database.TransactionManager.TopTransaction
If tr Is Nothing Then
Throw New Exception(ErrorStatus.NoActiveTransactions)
End If
Dim attDefClass As RXClass = RXClass.GetClass(GetType(AttributeDefinition))
Dim attDefs As New List(Of AttributeDefinition)()
For Each id As ObjectId In target
If id.ObjectClass = attDefClass Then
Dim attDef As AttributeDefinition = DirectCast(tr.GetObject(id, OpenMode.ForRead), AttributeDefinition)
attDefs.Add(attDef)
End If
Next
For Each id As ObjectId In target.GetBlockReferenceIds(True, False)
Dim br As BlockReference = DirectCast(tr.GetObject(id, OpenMode.ForWrite), BlockReference)
br.ResetAttributes(attDefs)
Next
If target.IsDynamicBlock Then
For Each id As ObjectId In target.GetAnonymousBlockIds()
Dim btr As BlockTableRecord = DirectCast(tr.GetObject(id, OpenMode.ForRead), BlockTableRecord)
For Each brId As ObjectId In btr.GetBlockReferenceIds(True, False)
Dim br As BlockReference = DirectCast(tr.GetObject(brId, OpenMode.ForWrite), BlockReference)
br.ResetAttributes(attDefs)
Next
Next
End If
End Sub
<System.Runtime.CompilerServices.Extension> _
Private Sub ResetAttributes(br As BlockReference, attDefs As List(Of AttributeDefinition))
Dim tm As TransactionManager = br.Database.TransactionManager
Dim attValues As New Dictionary(Of String, String)()
For Each id As ObjectId In br.AttributeCollection
If Not id.IsErased Then
Dim attRef As AttributeReference = DirectCast(tm.GetObject(id, OpenMode.ForWrite), AttributeReference)
attValues.Add(attRef.Tag, attRef.TextString)
attRef.Erase()
End If
Next
For Each attDef As AttributeDefinition In attDefs
Dim attRef As New AttributeReference()
attRef.SetAttributeFromBlock(attDef, br.BlockTransform)
If attValues IsNot Nothing AndAlso attValues.ContainsKey(attDef.Tag) Then
attRef.TextString = attValues(attDef.Tag.ToUpper())
End If
br.AttributeCollection.AppendAttribute(attRef)
tm.AddNewlyCreatedDBObject(attRef, True)
Next
End Sub
End Module