I'm working on an AutoCAD .net application that lists all block definitions in the active drawing in a TreeView Control with the attributes of that block listed a child nodes (AutoCAD 2015). When the user selects a block definition my code will highlight each block instance within the drawing. I also want it to Hihglight ONLY the attribute if an Attribute node is selected. Here is my code - for some reason the attributes are not being highlighted. Any assistance would be greatly appreciated.
Private Sub BlocksUltraTree_AfterSelect(sender As Object, e As Infragistics.Win.UltraWinTree.SelectEventArgs) Handles BlocksUltraTree.AfterSelect acActiveDocument = acDocumentManager.MdiActiveDocument acActiveDocumentDatabase = acActiveDocument.Database Dim acTrans As Transaction = acActiveDocumentDatabase.TransactionManager.StartTransaction Using acTrans 'clear any existing entity highlights Dim acBlockTable As BlockTable = acTrans.GetObject(acActiveDocumentDatabase.BlockTableId, OpenMode.ForRead) For Each acBlockTableRecordId As ObjectId In acBlockTable Dim acBlockTableRecord As BlockTableRecord = CType(acTrans.GetObject(acBlockTableRecordId, OpenMode.ForRead), BlockTableRecord) For Each acEntityId As ObjectId In acBlockTableRecord Dim myEnt As Entity = TryCast(acTrans.GetObject(acEntityId, OpenMode.ForRead), Entity) myEnt.Unhighlight() Next Next 'highlight selected blocks in the drawing Dim UserSelectedNode As Infragistics.Win.UltraWinTree.UltraTreeNode = Me.BlocksUltraTree.SelectedNodes(0) Dim acActiveDocumentEditor As Editor = acActiveDocument.Editor If UserSelectedNode.Tag = "Block" Then Dim acTypValAr(0) As TypedValue acTypValAr.SetValue(New TypedValue(DxfCode.BlockName, UserSelectedNode.Text), 0) Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr) Dim acSSPromptRslt As PromptSelectionResult acSSPromptRslt = acActiveDocumentEditor.SelectAll(acSelFtr) If acSSPromptRslt.Status = PromptStatus.OK Then For i = 0 To acSSPromptRslt.Value.Count - 1 Dim myBlk As BlockReference = TryCast(acTrans.GetObject(acSSPromptRslt.Value(i).ObjectId, OpenMode.ForRead), BlockReference) myBlk.Highlight() Next End If End If 'highlight selected attributes within the blocks in the drawing If UserSelectedNode.Tag = "Attribute" Then Dim acTypValAr(0) As TypedValue acTypValAr.SetValue(New TypedValue(DxfCode.BlockName, UserSelectedNode.Parent.Text), 0) Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr) Dim acSSPromptRslt As PromptSelectionResult acSSPromptRslt = acActiveDocumentEditor.SelectAll(acSelFtr) If acSSPromptRslt.Status = PromptStatus.OK Then For i = 0 To acSSPromptRslt.Value.Count - 1 Dim myBlk As BlockReference = TryCast(acTrans.GetObject(acSSPromptRslt.Value(i).ObjectId, OpenMode.ForRead), BlockReference) Dim attCol As AttributeCollection = myBlk.AttributeCollection For Each attObjId As ObjectId In attCol Dim att As AttributeReference = TryCast(acTrans.GetObject(attObjId, OpenMode.ForRead), AttributeReference) If Not att Is Nothing Then If att.Tag = UserSelectedNode.Text Then MsgBox(att.TextString) att.Highlight() End If End If Next Next End If End If End Using 'acTrans End Sub
Note that the msgbox (att.TextString) line is simply there to know I was indeed getting each seperate instance of that attribute within the drawing.
Solved! Go to Solution.
Solved by william.klawitter. Go to Solution.
Solved by norman.yuan. Go to Solution.
It looks like AttributeReference.Highlight() method has its own implementation rather than inherits Entity.Highlight(). In order so find a vailable solution to your question, I did a bit research and code practice, and I believe I have a fairly "OK" solution. Since the code and some description on my solution is a bit long to be post here as the reply to your question, I post it in my blog here:
http://drive-cad-with-code.blogspot.ca/2015/09/highlight-attributes-in-blockreference.html
HTH
Norman Yuan
norman.yuan
Thank you for your reply. I've implemented your solution into my project. I had to change it a bit because I only need a certain attribute within certain blocks highlighted. Here is my final code.
Imports Autodesk.AutoCAD.GraphicsInterface Imports Autodesk.AutoCAD.Geometry Imports Autodesk.AutoCAD.DatabaseServices Imports System.Linq Imports System.Collections.Generic Imports System Public Class AttributeHighlighter Implements IDisposable Private _tManager As TransientManager = TransientManager.CurrentTransientManager Private _entities As New List(Of Drawable)() Public Sub Dispose() Implements IDisposable.Dispose DisposeDrawables() End Sub Public Sub Highlight(db As Database, blkId As ObjectId, attTag As String) DisposeDrawables() CollectDrawables(db, blkId, attTag) For Each ent In _entities _tManager.AddTransient(ent, TransientDrawingMode.Highlight, 128, New IntegerCollection()) Next End Sub Public Sub Unhighlight() _tManager.EraseTransients(TransientDrawingMode.Highlight, 128, New IntegerCollection()) End Sub Private Sub DisposeDrawables() For Each ent In _entities ent.Dispose() Next _entities.Clear() End Sub Private Sub CollectDrawables(db As Database, id As ObjectId, attTag As String) Using tran As Object = db.TransactionManager.StartTransaction() Dim bref As BlockReference = TryCast(tran.GetObject(id, OpenMode.ForRead), BlockReference) If bref Is Nothing Then Else For Each attId As ObjectId In bref.AttributeCollection Dim att As AttributeReference = CType(tran.GetObject(attId, OpenMode.ForRead), AttributeReference) If att.Tag = attTag Then _entities.Add(TryCast(att.Clone(), Drawable)) End If Next End If tran.Commit() End Using End Sub End Class
'highlight selected attributes within the blocks in the drawing If UserSelectedNode.Tag = "Attribute" Then Dim acTypValAr(0) As TypedValue acTypValAr.SetValue(New TypedValue(DxfCode.BlockName, UserSelectedNode.Parent.Text), 0) Dim acSelFtr As SelectionFilter = New SelectionFilter(acTypValAr) Dim acSSPromptRslt As PromptSelectionResult acSSPromptRslt = acActiveDocumentEditor.SelectAll(acSelFtr) If acSSPromptRslt.Status = PromptStatus.OK Then For i = 0 To acSSPromptRslt.Value.Count - 1 Dim myBlk As BlockReference = TryCast(acTrans.GetObject(acSSPromptRslt.Value(i).ObjectId, OpenMode.ForRead), BlockReference) Dim attCol As AttributeCollection = myBlk.AttributeCollection For Each attObjId As ObjectId In attCol Dim att As AttributeReference = TryCast(acTrans.GetObject(attObjId, OpenMode.ForRead), AttributeReference) If Not att Is Nothing Then If att.Tag = UserSelectedNode.Text Then Dim hl As New AttributeHighlighter() hl.Highlight(acActiveDocumentDatabase, myBlk.ObjectId, att.Tag) acActiveDocumentEditor.UpdateScreen() End If End If Next Next End If