0

I'm currently inserting dynamic blocks via an ASP.NET Core 8 Web API (AutoCAD 2026, .NET 8). These blocks include attributes whose default values contain field expressions, referencing dynamic properties using BlockPlaceholder. I don't need or want to change this by default value. This is exactly what I need to show.

When I insert the blocks manually in AutoCAD, the attributes appear correctly and display the expected field content. However, when I insert them programmatically using BlockReference, the attributes do not appear visibly in the drawing — even though they exist — unless I run ATTSYNC manually.

Using ATTSYNC is a terrible idea (I'm working with a huge amount of blocks, 2000++).

I already try to add the attribute references for each newly created block reference and played around with some methods but nothing worked.

Could anybody please give me a hand with this?

This is my general code so far:

public object[,] DibujarDB(string blkName, string[] propsName, object[,] propsValue, ActualizadorFormulario actualizador)
{
    var doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
    var db = doc.Database;
    var ed = doc.Editor;

    using (var trans = db.TransactionManager.StartTransaction())
    {
        try
        {
            // Obtener la tabla de bloques
            var bt = (BlockTable)trans.GetObject(db.BlockTableId, OpenMode.ForRead);

            if (!bt.Has(blkName))
            {
                ed.WriteMessage($"\nEl bloque '{blkName}' no existe.");
                return null;
            }

            // Acceder al espacio modelo y a la tabla de capas
            var btr = (BlockTableRecord)trans.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
            var lt = (LayerTable)trans.GetObject(db.LayerTableId, OpenMode.ForRead);

            int rows = propsValue.GetLength(0);
            string miEstado;
            var blkId = bt[blkName];

            // Mapeo nombre → índice de columnas en la tabla propsValue
            var propIndices = propsName
                    .Select((name, index) => new { name, index })
                    .ToDictionary(p => p.name, p => p.index);

            // Índices clave
            int idxDibujar = propIndices["DIBUJAR"];
            int idxHandler = propIndices["HANDLER"];
            int idxCX = propIndices["CX"];
            int idxCY = propIndices["CY"];
            int idxCZ = propIndices["CZ"];
            int idxANG = propIndices["ANG"];
            int idxCAPA = propIndices["CAPA"];
            int idxESCX = propIndices["ESCX"];
            int idxESCY = propIndices["ESCY"];
            int idxESCZ = propIndices["ESCZ"];

            // Asegurar que todas las capas existan
            RevisionCapas(trans, lt, idxCAPA, propsValue);

            // Nombres de propiedades dinámicas (a partir de la columna 12)
            string[] dynPropNames = propsName.Skip(11).ToArray();

            // Obtener definiciones de atributos NO constantes del bloque base
            var blkDef = (BlockTableRecord)trans.GetObject(blkId, OpenMode.ForRead);
            var attDefs = blkDef
                    .Cast<ObjectId>()
                    .Where(id => id.ObjectClass.Name == "AcDbAttributeDefinition")
                    .Select(id => (AttributeDefinition)trans.GetObject(id, OpenMode.ForRead))
                    .Where(attDef => !attDef.Constant)
                    .ToArray();

            // Avisar al usuario
            miEstado = $"Dibujando {blkName}.";
            actualizador.ActualizarEstado(miEstado);

            for (int i = 0; i < rows; i++)
            {
                // Verificar si se debe dibujar esta fila
                var dibujarVal = propsValue[i, idxDibujar]?.ToString();

                if (!string.Equals(dibujarVal, "SI", StringComparison.OrdinalIgnoreCase) &&
                    !string.Equals(dibujarVal, "TRUE", StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                // Validar y convertir coordenadas, ángulo y escala
                if (!double.TryParse(propsValue[i, idxCX]?.ToString(), out double cx) ||
                    !double.TryParse(propsValue[i, idxCY]?.ToString(), out double cy) ||
                    !double.TryParse(propsValue[i, idxCZ]?.ToString(), out double cz) ||
                    !double.TryParse(propsValue[i, idxANG]?.ToString(), out double ang) ||
                    !double.TryParse(propsValue[i, idxESCX]?.ToString(), out double escX) ||
                    !double.TryParse(propsValue[i, idxESCY]?.ToString(), out double escY) ||
                    !double.TryParse(propsValue[i, idxESCZ]?.ToString(), out double escZ))
                {
                    ed.WriteMessage($"\nError: Datos inválidos en la fila {i}");
                    continue;
                }

                string capa = propsValue[i, idxCAPA]?.ToString() ?? "0";

                // Crear instancia del bloque
                var blkRef = new BlockReference(new Point3d(cx, cy, cz), blkId)
                    {
                        Rotation = ang,
                        ScaleFactors = new Scale3d(escX, escY, escZ),
                        Layer = capa
                    };

                // Añadimos el bloque al espacio modelo
                btr.AppendEntity(blkRef);
                trans.AddNewlyCreatedDBObject(blkRef, true);

                // Guardamos el handler en la tabla de valores
                propsValue[i, idxHandler] = blkRef.Handle.ToString();

                // Obtenemos los campos asociados a los atributos del bloque
                var camposAtributos = InfoAtributos(blkRef, blkName);

                foreach (var attDef in attDefs)
                {
                    var attRef = new AttributeReference();
                    attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
                    attRef.TextString = "";

                    if (camposAtributos.TryGetValue(attDef.Tag, out Field campo))
                    {
                        attRef.SetField(campo);
                        campo.Evaluate(); // Forzamos la evaluación del campo
                    }
                    else if (attDef.Tag == "HANDLE") // texto plano
                    {
                        attRef.TextString = propsValue[i, idxHandler].ToString();
                    }

                    blkRef.AttributeCollection.AppendAttribute(attRef);
                    trans.AddNewlyCreatedDBObject(attRef, true);
                }

                // Asignar propiedades dinámicas si aplican
                foreach (var propName in dynPropNames)
                {
                    DynamicBlockReferenceProperty prop = blkRef.DynamicBlockReferencePropertyCollection
                            .Cast<DynamicBlockReferenceProperty>()
                            .FirstOrDefault(p => p.PropertyName == propName)!;

                    if (prop != null)
                    {
                        var valStr = propsValue[i, propIndices[propName]]?.ToString();

                        if (valStr != null && prop.Value.ToString() != valStr)
                        {
                            try
                            {
                                prop.Value = Convert.ChangeType(valStr, prop.Value.GetType());
                            }
                            catch
                            {
                                ed.WriteMessage($"\nAdvertencia: No se pudo asignar '{valStr}' a la propiedad '{propName}' en fila {i}");
                            }
                        }
                    }
                }

                // Reportar progreso
                actualizador.ActualizarProgresoProceso();
            }

            // Confirmar la transacción
            trans.Commit();

            // Finalizar estado
            miEstado = $"Terminamos con ({blkName})";
            actualizador.ActualizarEstado(miEstado);

            return propsValue;
        }
        catch (System.Exception ex)
        {
            ed.WriteMessage($"\nError: {ex.Message}");
        }

        return null;
    }
}

private Dictionary<string, Field> InfoAtributos(BlockReference blkRef, string blkName)
{
    var resultado = new Dictionary<string, Field>();

    if (blkName == "BR_SLE_SG_V01")
    {
        // Campo correcto para propiedad BARRA_NO del mismo bloque dinámico
        string fieldCode = @"%<\AcObjProp Object(%<\_BlkRef>%).BARRA_NO \f ""%s"">%";

        var field = new Field
            {
                EvaluationOption = FieldEvaluationOptions.Automatic
            };
        field.SetFieldCode(fieldCode);

        resultado.Add("000_000", field);
    }

    return resultado;
}

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.