.NET
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic to the Top
- Bookmark
- Subscribe
- Printer Friendly Page
how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Hello,experts
I have a question,It's about "Block Properties Table",I want to use a Block Properties Table to manage a Dynamic
Block.
I have defiened a Dynamic Block a and its Block Properties Table in Autocad2010,this is the screenshot of the
Block Properties Table(a1:d1=100,d2=200;a2:d1=100,d2=400;a3:d1=100,
Now I want to insert the Dynamic Block using .NET API.after I input a command,the block of a2(d1=100,d2=400)
is inserted.
I have the code about it from Help,but the code is not complete,Can you help me finish the code which can achieve my goal?
Thank you very much!
this is the Dynamic Block
this is the the screenshot of the Block Properties Table
the result:
the code about it from Help:
[CommandMethod("readBlockTable")]
static public void CmdReadBlockTable()
{
Editor ed = Application.DocumentManager.
MdiActiveDocument.Editor;
// select a block reference
PromptEntityOptions peo = new PromptEntityOptions(
"Select a dynamic block reference: ");
peo.SetRejectMessage("Only block reference");
peo.AddAllowedClass(typeof(BlockReference), false);
PromptEntityResult per = ed.GetEntity(peo);
if (per.Status != PromptStatus.OK) return;
ObjectId blockRefId = per.ObjectId;
// get the database and start a transaction
Database db = Application.DocumentManager.
MdiActiveDocument.Database;
using (Transaction trans = db.
TransactionManager.StartTransaction())
{
// open the dynamic block reference
BlockReference blockRef = trans.GetObject(
blockRefId, OpenMode.ForRead) as BlockReference;
if (!blockRef.IsDynamicBlock) return;
// get the dynamic block table definition
BlockTableRecord blockDef = trans.GetObject(
blockRef.DynamicBlockTableRecord,
OpenMode.ForRead) as BlockTableRecord;
// open the extension dictionary
if (blockDef.ExtensionDictionary.IsNull) return;
DBDictionary extDic = trans.GetObject(
blockDef.ExtensionDictionary, OpenMode.ForRead)
as DBDictionary;
// open the ENHANCEDBLOCK dictionary
Autodesk.AutoCAD.Internal.DatabaseServices.EvalGra
trans.GetObject(extDic.GetAt("ACAD_ENHANCEDBLOCK")
OpenMode.ForRead) as EvalGraph;
int[] nodeIds = graph.GetAllNodes();
foreach (uint nodeId in nodeIds)
{
// open the node ID
DBObject node = graph.GetNode(nodeId,
OpenMode.ForRead, trans);
// check is if the correct type
if (!(node is BlockPropertiesTable)) continue;
// convert the object
BlockPropertiesTable table =
node as BlockPropertiesTable;
// ok, we have the data, let's show it...
// get the number of columns
int columns = table.Columns.Count;
int currentRow = 0;
foreach (
BlockPropertiesTableRow row
in table.Rows)
{
currentRow++;
}
}
}
}
Solved! Go to Solution.
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
I've done minimum tests with provided dwg-file:
using System;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Internal.DatabaseServices;
using AcAp = Autodesk.AutoCAD.ApplicationServices;
using AcDb = Autodesk.AutoCAD.DatabaseServices;
using AcGe = Autodesk.AutoCAD.Geometry;
using AcEd = Autodesk.AutoCAD.EditorInput;
using AcId = Autodesk.AutoCAD.Internal.DatabaseServices;
[assembly: CommandClass(typeof(Rivilis.BPTTest))]
#pragma warning disable 618
namespace Rivilis
{
public class BPTTest
{
[CommandMethod("InsBlockWithBPT")]
public static void InsBlockWithBPT()
{
AcAp.Document doc = AcAp.Application.DocumentManager.MdiActiveDocument ;
AcEd.Editor ed = doc.Editor;
AcDb.Database db = doc.Database;
AcEd.PromptResult rs = ed.GetString("\nEnter block name: ");
if (rs.Status != PromptStatus.OK) return;
AcDb.ObjectId idBTR = AcDb.ObjectId.Null, idBref;
using (AcDb.BlockTable bt = db.BlockTableId.Open(OpenMode.ForRead) as AcDb.BlockTable) {
if (bt != null) idBTR = bt[rs.StringResult];
}
if (idBTR.IsNull) {
ed.WriteMessage("\nDatabase has not block \"{0}\"", rs.StringResult);
return;
}
AcEd.PromptPointResult rsp = ed.GetPoint("\nEnter position: ");
if (rsp.Status != PromptStatus.OK) return;
using (AcDb.Transaction tr = doc.TransactionManager.StartTransaction()) {
AcDb.BlockTableRecord btr =
tr.GetObject(idBTR, OpenMode.ForRead) as AcDb.BlockTableRecord;
AcDb.BlockTableRecord btrSpace =
tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite) as AcDb.BlockTableRecord;
if (btr != null && btrSpace != null) {
AcDb.BlockReference brf =
new AcDb.BlockReference(rsp.Value.TransformBy(ed.Curre ntUserCoordinateSystem), idBTR);
idBref = btrSpace.AppendEntity(brf);
tr.AddNewlyCreatedDBObject(brf, true);
if (brf.IsDynamicBlock) {
AcDb.BlockTableRecord btrDyn =
tr.GetObject(brf.DynamicBlockTableRecord, OpenMode.ForRead) as AcDb.BlockTableRecord;
if (btrDyn != null && !btrDyn.ExtensionDictionary.IsNull) {
AcDb.DBDictionary extDic =
tr.GetObject(btrDyn.ExtensionDictionary, OpenMode.ForRead) as AcDb.DBDictionary;
if (extDic != null) {
AcId.EvalGraph graph =
tr.GetObject(extDic.GetAt("ACAD_ENHANCEDBLOCK"), OpenMode.ForRead) as AcId.EvalGraph;
int[] nodeIds = graph.GetAllNodes();
foreach (uint nodeId in nodeIds) {
DBObject node = graph.GetNode(nodeId, OpenMode.ForRead, tr);
if (!(node is BlockPropertiesTable)) continue;
AcDb.BlockPropertiesTable bpt = node as AcDb.BlockPropertiesTable;
int currentRow = SelectRowNumber(ref bpt);
AcDb.BlockPropertiesTableRow row = bpt.Rows[currentRow];
List<string> nameProps = new List<string>();
for (int i = 0; i < bpt.Columns.Count; i++) {
nameProps.Add(bpt.Columns[i].Parameter.Name);
}
AcDb.DynamicBlockReferencePropertyCollection dynPropsCol =
brf.DynamicBlockReferencePropertyCollection;
foreach (AcDb.DynamicBlockReferenceProperty dynProp in dynPropsCol) {
int i = nameProps.FindIndex(delegate(string s) { return s == dynProp.PropertyName; });
if (i >= 0 && i < nameProps.Count) {
try {
dynProp.Value = row[i].AsArray()[0].Value;
} catch {
ed.WriteMessage("\nCan not set to {0} value={1}",
dynProp.PropertyName, row[i].AsArray()[0].Value);
}
}
}
}
}
}
} else {
ed.WriteMessage("\nBlock \"{0}\" is not dynamic", rs.StringResult);
}
}
tr.Commit();
}
}
public static int SelectRowNumber(ref BlockPropertiesTable bpt)
{
AcEd.Editor ed = AcAp.Application.DocumentManager.MdiActiveDocument .Editor;
int columns = bpt.Columns.Count;
int rows = bpt.Rows.Count;
int currentRow = 0, currentColumn = 0;
ed.WriteMessage("\n");
for (currentColumn = 0; currentColumn < columns; currentColumn++) {
ed.WriteMessage("{0}; ", bpt.Columns[currentColumn].Parameter.Name);
}
foreach (BlockPropertiesTableRow row in bpt.Rows) {
ed.WriteMessage("\n[{0}]:\t", currentRow);
for (currentColumn = 0; currentColumn < columns; currentColumn++) {
TypedValue[] columnValue = row[currentColumn].AsArray();
foreach (TypedValue tpVal in columnValue) {
ed.WriteMessage("{0}; ", tpVal.Value);
}
ed.WriteMessage("|");
}
currentRow++;
}
AcEd.PromptIntegerResult res;
string.Format("0-{0}", rows - 1);
while ((res = ed.GetInteger(string.Format("\nSelect row number (0-{0}): ", rows - 1))).Status == PromptStatus.OK) {
if (res.Value >= 0 && res.Value <= rows) return res.Value;
}
return -1;
}
}
}
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Dynamic block uses the extension dictionary ACAD_ENHANCEDBLOCK in DynamicBlockTableRecord to store all dynamic block definitions (grips, visibility values,...), and DynamicBlockReferencePropertyCollection in BlockReference to stores instances of those dynamic definitions.
Your Block Properties Table with three defined columns (user1, d1, d2) is stored in ACAD_ENHANCEDBLOCK, and the option of this Block Properties Table is stored in DynamicBlockReferencePropertyCollection. So to change the display of this dynamic block, you just set DynamicBlockReferenceProperty.Value of a found DynamicBlockReferenceProperty.Name.
The Block Properties Table inside the dynamic block uses the first column (user1) as a key field to identify the presentation of this block, so just use the code snippet to update its dynamic attribute: if PropertyName == "user1" then Value = "a3"
using (Transaction trans = db.TransactionManager.StartTransaction())
{
// open the dynamic block reference
BlockReference blockRef = trans.GetObject(blockRefId, OpenMode.ForRead) as BlockReference;
if (!blockRef.IsDynamicBlock) return;
DynamicBlockReferencePropertyCollection properties = blockRef.DynamicBlockReferencePropertyCollection;
for (int i = 0; i < properties.Count; i++)
{
DynamicBlockReferenceProperty property = properties[i];
if (property.PropertyName == "user1")
{
property.Value = "a3"; // Change your option here
// Need code to update the dynamic block after updating a property from block properties table
break;
}
}
trans.Commit();
}
This above code does change the value of a block properties table but does not update the block display itself. Even I run REGEN or close it and open again. So we need the API to update dynamic block geometry entities after changing its custom attributes.
-Khoa
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Hi Alexander,
I came up with my answer before your post and only had chance to post after the lunch. I did not see carefully your code and even tried to run it. Anyway, I just gave the idea of the difference between ACAD_ENHANCEDBLOCK and DynamicBlockReferencePropertyCollection. No need to lookup ACAD_ENHANCEDBLOCK extension dictionary unless we want to change the dynamic block definition. Just to use DynamicBlockReferencePropertyCollection if we want to change dynamic block custom attributes.
-Khoa
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
khoa.ho wrote:
...Just to use DynamicBlockReferencePropertyCollection if we want to change dynamic block custom attributes...
Yes. But you have to know not only "user1" value, but also values of "d1" and "d2". And those values are in BlockPropertiesTable.
P.S.: This topic has a "history" in ObjectARX board.
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Hi Alexander,
You are right, I assume the user knows the value to pass. The code is just for demonstration. I don't track ObjectARX forum so I did not know your answer was also there as the poster repeated twice. It's good to know the same resource over there.
-Khoa
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
you are very great!
Thank you very much!
Re: how to use a Block Properties Table of a a Dynamic Block using .NET API?
- Mark as New
- Bookmark
- Subscribe
- Subscribe to RSS Feed
- Highlight
- Email to a Friend
- Report Inappropriate Content
Thank you very much!




