Hi,
I'm using the below method to set an attribute value. The code runs as expected without any errors. Even attRef.TextString value changes in the method. But when the code completes the attribute value does not change in the drawing. I'm not sure if a setting within AutoCAD is interfering or the code is the issue.
I've also attached a sample block.
The attribute in question has the following modes set.
I'm using AutoCAD 2025 trial.
Could any one please help?
Here is the method.
public static bool SetAttributeValue(this BlockReference br, Transaction tr, string tag, string value)
{
bool valueSet = false;
//using (Transaction tr = Active.Database.TransactionManager.StartTransaction())
//{
foreach (ObjectId id in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(id,OpenMode.ForRead);
if (attRef.Tag.Equals(tag))
{
attRef.UpgradeOpen();
attRef.TextString = value;
valueSet = true;
break;
}
}
//tr.Commit();
//}
return valueSet;
}
Here is the test method I'm using,
[CommandMethod("testAttOp")]
public void testAttOp()
{
PromptEntityOptions peo = new PromptEntityOptions("\nSelect Block: ");
peo.SetRejectMessage("\nSelect block only.");
peo.AddAllowedClass(typeof(BlockReference), true);
peo.AppendKeywordsToMessage = true;
PromptEntityResult per = Active.Editor.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
ObjectId objectId = per.ObjectId;
using (Transaction tr = Active.Database.TransactionManager.StartTransaction())
{
BlockReference br = (BlockReference)tr.GetObject(objectId, OpenMode.ForRead);
string value = br.GetAttributeValue("TEST");
Active.Editor.WriteMessage("\n" + value);
bool changed = br.SetAttributeValue(tr, "TEST", "1000");
if (changed)
{
Active.Editor.WriteMessage("\n" + br.GetAttributeValue("TEST"));
}
tr.Commit();
}
}
Solved! Go to Solution.
Hi,
I'm using the below method to set an attribute value. The code runs as expected without any errors. Even attRef.TextString value changes in the method. But when the code completes the attribute value does not change in the drawing. I'm not sure if a setting within AutoCAD is interfering or the code is the issue.
I've also attached a sample block.
The attribute in question has the following modes set.
I'm using AutoCAD 2025 trial.
Could any one please help?
Here is the method.
public static bool SetAttributeValue(this BlockReference br, Transaction tr, string tag, string value)
{
bool valueSet = false;
//using (Transaction tr = Active.Database.TransactionManager.StartTransaction())
//{
foreach (ObjectId id in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(id,OpenMode.ForRead);
if (attRef.Tag.Equals(tag))
{
attRef.UpgradeOpen();
attRef.TextString = value;
valueSet = true;
break;
}
}
//tr.Commit();
//}
return valueSet;
}
Here is the test method I'm using,
[CommandMethod("testAttOp")]
public void testAttOp()
{
PromptEntityOptions peo = new PromptEntityOptions("\nSelect Block: ");
peo.SetRejectMessage("\nSelect block only.");
peo.AddAllowedClass(typeof(BlockReference), true);
peo.AppendKeywordsToMessage = true;
PromptEntityResult per = Active.Editor.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
ObjectId objectId = per.ObjectId;
using (Transaction tr = Active.Database.TransactionManager.StartTransaction())
{
BlockReference br = (BlockReference)tr.GetObject(objectId, OpenMode.ForRead);
string value = br.GetAttributeValue("TEST");
Active.Editor.WriteMessage("\n" + value);
bool changed = br.SetAttributeValue(tr, "TEST", "1000");
if (changed)
{
Active.Editor.WriteMessage("\n" + br.GetAttributeValue("TEST"));
}
tr.Commit();
}
}
Solved! Go to Solution.
Solved by _gile. Go to Solution.
Solved by shricharana_bharadwaj. Go to Solution.
Hi, thank you for the reply.
So could it be an AutoCAD bug?
I tried resetting AutoCAD to default but that is not helping.
Hi, thank you for the reply.
So could it be an AutoCAD bug?
I tried resetting AutoCAD to default but that is not helping.
So, I'm not sure why this fixed it or what the relation is, but
I'm was using the below method to get the value of the attribute In which I was using OpenCloseTransaction for
transaction. This seems to be the cause for the attribute value not changing.
Calling GetAttributeValue() after setting the value was causing the issue, somehow. I don't understand how that could interfere.
Changing transaction in GetAttributeValue() to DB.TransactionManager.StartTransaction() fixed it.
Could you please tell me why this behavior was happening when using OpenCloseTransaction?
public static string GetAttributeValue(this BlockReference br, string attributeTag)
{
string ret = string.Empty;
using (Transaction tr = new OpenCloseTransaction())
{
foreach (ObjectId ob in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(ob, OpenMode.ForRead);
if (attRef.Tag.Equals(attributeTag, StringComparison.CurrentCultureIgnoreCase))
{
// add an entry to the dictionary
ret = attRef.TextString;
// break the loop
break;
}
}
tr.Abort();
}
return ret;
}
So, I'm not sure why this fixed it or what the relation is, but
I'm was using the below method to get the value of the attribute In which I was using OpenCloseTransaction for
transaction. This seems to be the cause for the attribute value not changing.
Calling GetAttributeValue() after setting the value was causing the issue, somehow. I don't understand how that could interfere.
Changing transaction in GetAttributeValue() to DB.TransactionManager.StartTransaction() fixed it.
Could you please tell me why this behavior was happening when using OpenCloseTransaction?
public static string GetAttributeValue(this BlockReference br, string attributeTag)
{
string ret = string.Empty;
using (Transaction tr = new OpenCloseTransaction())
{
foreach (ObjectId ob in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(ob, OpenMode.ForRead);
if (attRef.Tag.Equals(attributeTag, StringComparison.CurrentCultureIgnoreCase))
{
// add an entry to the dictionary
ret = attRef.TextString;
// break the loop
break;
}
}
tr.Abort();
}
return ret;
}
This is because you abort the OpenCloseTransaction in the GetAttributeValue method.
Even when only opening objects for read, commit the transaction is better/cheaper than aborting it.
Anyway, it would be a better practice to pass to the GetAttributeValue method the transaction used to open its BlockReference argument as you do with your SetAttributeValue method.
public static string GetAttributeValue(this BlockReference br, Transaction tr, string attributeTag)
{
foreach (ObjectId ob in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(ob, OpenMode.ForRead);
if (attRef.Tag.Equals(attributeTag, StringComparison.CurrentCultureIgnoreCase))
{
return attRef.TextString;
}
}
return string.Empty;
}
This is because you abort the OpenCloseTransaction in the GetAttributeValue method.
Even when only opening objects for read, commit the transaction is better/cheaper than aborting it.
Anyway, it would be a better practice to pass to the GetAttributeValue method the transaction used to open its BlockReference argument as you do with your SetAttributeValue method.
public static string GetAttributeValue(this BlockReference br, Transaction tr, string attributeTag)
{
foreach (ObjectId ob in br.AttributeCollection)
{
AttributeReference attRef = (AttributeReference)tr.GetObject(ob, OpenMode.ForRead);
if (attRef.Tag.Equals(attributeTag, StringComparison.CurrentCultureIgnoreCase))
{
return attRef.TextString;
}
}
return string.Empty;
}
Can't find what you're looking for? Ask the community or share your knowledge.