.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Unable to change attribute text string in block reference.

4 REPLIES 4
SOLVED
Reply
Message 1 of 5
shricharana_bharadwaj
311 Views, 4 Replies

Unable to change attribute text string in block reference.

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.

shricharana_bharadwaj_0-1721634657418.png

 

 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();
    }
}

  

Labels (3)
4 REPLIES 4
Message 2 of 5

Hi,

There's nothing wrong with the code you posted.

I tested it with the attached drawing and it worked as expected.



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 5

Hi, thank you for the reply.

 

So could it be an AutoCAD bug?

I tried resetting AutoCAD to default but that is not helping.

Message 4 of 5

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;
}

 

Message 5 of 5

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;
}

 

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

AutoCAD Inside the Factory


Autodesk Design & Make Report