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

Setting a Group of Layers Visible in a Viewport

51 REPLIES 51
Reply
Message 1 of 52
mgorecki
2003 Views, 51 Replies

Setting a Group of Layers Visible in a Viewport

I have a dialog box that has 2 list boxes.  One box has the available layers in it, while the other will contain the selected layers.  I want to use those selected layers as a list of layers that will be visible in a particular viewport.  I have searched all over to find information on what kind of list I would need and how could I use the list with a viewport, but all I've found is info for one layer becoming visible.

I'm also looking into "FreezeLayersInViewport" but info sure seems limited.

Any help would be appreciated.

 

Thanks,

Mark

51 REPLIES 51
Message 2 of 52
Artvegas
in reply to: mgorecki

Hi Mark,

 

I think you are on track with FreezeLayersInViewport() method.

 

The trick with this method is to:

1. create an ObjectIdCollection that contains the ObjectIds for the layers you want to freeze in the viewport; and

2. pass ObjectIdCollection.GetEnumerator() into the FreezeLayersInViewport method.

 

Below is a C# sample that I quickly tested. It prompts the user to select a viewport and then freezes layers named "Blue" and "Red".

 

Hope this helps.

 

Art.

 

 

[CommandMethod("FreezeLayersInViewport")]
public static void FreezeLayersInViewport() {

     
Document doc = Application.DocumentManager.MdiActiveDocument;
     
Database db = doc.Database;
     
Editor ed = doc.Editor;

      // Prompt to select paper space Viewport.
      PromptEntityOptions peo = newPromptEntityOptions("\nSelect floating paper space viewport: ");
      peo.SetRejectMessage("\nFloating paper space viewport not selected. Try again...");
      peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Viewport), true);
      PromptEntityResult per = ed.GetEntity(peo);

      // Check prompt result status.
      if (per.Status != PromptStatus.OK) {
           
return;
      }

     
using (Transaction tr = db.TransactionManager.StartTransaction()) {

           
// ObjectIdCollection for layers to be frozen.
           
ObjectIdCollection layerIds = newObjectIdCollection();

           
// Iterate layers and add ObjectIds to ObjectIdCollection.
            LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) asLayerTable;
            foreach (ObjectId id in lt) {
                 
LayerTableRecord ltr = tr.GetObject(id, OpenMode.ForRead) asLayerTableRecord;
                 
if (ltr.Name == "Blue" || ltr.Name == "Red") {
                       
layerIds.Add(id);
                 
}
            }

            // Selected Viewport for write.
            Autodesk.AutoCAD.DatabaseServices.Viewport vp
               = tr.GetObject(per.ObjectId,
OpenMode.ForWrite) as AutoCAD.DatabaseServices.Viewport;

            // Freeze viewport layers.
            vp.FreezeLayersInViewport(layerIds.GetEnumerator());

            tr.Commit();
      }
}

Message 3 of 52
Artvegas
in reply to: Artvegas

Message 4 of 52
mgorecki
in reply to: Artvegas

Hi Art,

Thanks for the example and the link.  I had actually run across the link in my search, and used some of the info to launch other searches.

I'm going to try and implement your example in my code.  I'll let you know how it goes.

 

Thanks again,

Mark

Message 5 of 52
Artvegas
in reply to: mgorecki

Hi Mark,

 

I noticed that when i copy+pasted my sample above there were a couple of typos. I've re-typed the sample below.

 

Art

 

 

[CommandMethod("FreezeLayersInViewport")]
public static void FreezeLayersInViewport() {

     
Document doc = Application.DocumentManager.MdiActiveDocument;
     
Database db = doc.Database;
     
Editor ed = doc.Editor;

      // Prompt to select paper space Viewport.
      PromptEntityOptions peo = new PromptEntityOptions("\nSelect floating paper space viewport: ");
      peo.SetRejectMessage("\nFloating paper space viewport not selected. Try again...");
      peo.AddAllowedClass(typeof(Autodesk.AutoCAD.DatabaseServices.Viewport), true);
      PromptEntityResult per = ed.GetEntity(peo);

      // Check prompt result status.
      if (per.Status != PromptStatus.OK) {
           
return;
      }

     
using (Transaction tr = db.TransactionManager.StartTransaction()) {

           
// ObjectIdCollection for layers to be frozen.
           
ObjectIdCollection layerIds = new ObjectIdCollection();

           
// Iterate layers and add ObjectIds to ObjectIdCollection.
            LayerTable lt = tr.GetObject(db.LayerTableId, OpenMode.ForRead) as LayerTable;
            foreach (ObjectId id in lt) {
                 
LayerTableRecord ltr = tr.GetObject(id, OpenMode.ForRead) as LayerTableRecord;
                 
if (ltr.Name == "Blue" || ltr.Name == "Red") {
                       
layerIds.Add(id);
                 
}
            }

            // Selected Viewport for write.
            Autodesk.AutoCAD.DatabaseServices.Viewport vp
               = tr.GetObject(per.ObjectId,
OpenMode.ForWrite) as Autodesk.AutoCAD.DatabaseServices.Viewport;

            // Freeze viewport layers.
            vp.FreezeLayersInViewport(layerIds.GetEnumerator());

            tr.Commit();
      }
}

Message 6 of 52
mgorecki
in reply to: Artvegas

Hi Art,

Thanks a lot.  I appreciate the code, plus the comments in the code.  It really helps me learn.  After taking your code apart and looking up info on ObjectIdCollections, I think I have a better understanding of them.

I do have another question, if you don't mind.  I have a dialog that has two listboxes.  One is the available layers, and the other is the layers selected from the first listbox.  I'm trying to get a layer ID collection of the selected layers, but I don't think I'm going about it the right way.

Here is my code so far, it doesn't work, but I'm still working on it.

            Dim layerIds As ObjectIdCollection = New ObjectIdCollection()
            Dim lt As LayerTable = vpLayertrans.GetObject(db.LayerTableId, OpenMode.ForRead)
            Dim layerId As ObjectId
            Dim selectedLayerName As String
            Dim i As Integer

            For i = 0 To lstAvailableLayers.SelectedItems.Count - 1
                ' Add only the selected layers to the right side list box
                lstLayersToUse.Items.Add(lstAvailableLayers.SelectedItems(i))
                selectedLayerName = (lstAvailableLayers.SelectedItems(i))
                Dim ltr As LayerTableRecord = lt(selectedLayerName).GetObject(OpenMode.ForRead)
                layerId = ltr.ObjectId
                layerIds.Add(layerId)
            Next

 How do I get the layer ID's from the listbox into the layerIDs collection?  I was also thinking I would have to do another "for each" and compare each layer in the layertable to each of the selected layers, but that seemed like a lot extra when the layers being added to the second list box were available as they were being added.

 

Thanks,

Mark

 

Message 7 of 52
Artvegas
in reply to: mgorecki

Hi Mark,

 

You're welcome.

 

Looks like you're on the right track. Yes I think you'll need some kind of loop to create the ObjectIdCollection.

 

One thing you might keep in mind is that you don't actually need to seperately open each LayerTableRecord in order to get each layer's ObjectId. Instead you can simply get the ObjectId for a particular layer as follows:

 

      Dim layerIds As ObjectIdCollection = New ObjectIdCollection()
      Dim lt As LayerTable = vpLayertrans.GetObject(db.LayerTableId, OpenMode.ForRead)

      For i = 0 To lstLayersToFreeze.SelectedItems.Count - 1
           layerIds.Add(lt(lstLayersToFreeze.SelectedItems(i)))
      Next

     ' Insert code here to freeze viewport layers using ObjectIdCollection.

 

Cheers,

Art

Message 8 of 52
mgorecki
in reply to: Artvegas

Imports System.Windows.Forms
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.ApplicationServices.Application
Imports Autodesk.AutoCAD.EditorInput

Public Class dialogTitleText
    Public newTextTitle As String, newTextDieSide As String, layerIds As ObjectIdCollection
    Public Sub New(ByVal textTitle As String, ByVal textDieSide As String)
        ' This call is required by the Windows Form Designer.
        InitializeComponent()
        ' By default, the label and textbox for the die side text is not visible
        ' If there actually is text to change, then they becomes visible
        If textDieSide <> "" Then
            txtDieSide.Visible = True
            lblDieSide.Visible = True
        End If
        ' This puts the attribute text into the text boxes
        txtSheetTitle.Text = textTitle
        txtDieSide.Text = textDieSide

    End Sub
    Public Sub MaindialogTitleText_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim myDWG As Autodesk.AutoCAD.ApplicationServices.Document
        Dim myDB As Autodesk.AutoCAD.DatabaseServices.Database
        Dim myTransMan As Autodesk.AutoCAD.DatabaseServices.TransactionManager
        Dim myTrans As Autodesk.AutoCAD.DatabaseServices.Transaction

        myDWG = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
        myDB = myDWG.Database
        myTransMan = myDWG.TransactionManager
        myTrans = myTransMan.StartTransaction

        Dim myLT As Autodesk.AutoCAD.DatabaseServices.LayerTable
        Dim myLTR As Autodesk.AutoCAD.DatabaseServices.LayerTableRecord
        Dim mySTE As Autodesk.AutoCAD.DatabaseServices.SymbolTableEnumerator

        myLT = myDB.LayerTableId.GetObject(Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead)
        mySTE = myLT.GetEnumerator
        While mySTE.MoveNext
            myLTR = mySTE.Current.GetObject(Autodesk.AutoCAD.DatabaseServices.OpenMode.ForRead)
            lstAvailableLayers.Items.Add(myLTR.Name)
        End While
        myTrans.Dispose()
    End Sub

    ReadOnly Property selectedLayers() As ObjectIdCollection
        Get
            Return layerIds
        End Get
    End Property

    Private Sub OK_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles OK_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.Close()
    End Sub

    Private Sub Cancel_Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Cancel_Button.Click
        Me.DialogResult = System.Windows.Forms.DialogResult.Cancel
        Me.Close()
    End Sub

    Private Sub btnMoveLayers_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnMoveLayers.Click
        Dim doc As Document = DocumentManager.MdiActiveDocument
        Dim db As Database = doc.Database
        Dim ed As Editor = doc.Editor
        Dim vpLayertrans As Transaction = db.TransactionManager.StartTransaction()

        '  You must select at least one layer from the list
        If lstAvailableLayers.SelectedIndex < 0 Then
            MsgBox("You must select at least one layer", MsgBoxStyle.Exclamation, "Error")
        Else
            ' Copies the selected items from the available list to the layers to use list
            ' Also, it will create an object ID collection of the layers
            ' ObjectIdCollection for layers to be frozen.
            Dim layerIds As ObjectIdCollection = New ObjectIdCollection()
            Dim lt As LayerTable = vpLayertrans.GetObject(db.LayerTableId, OpenMode.ForRead)
            Dim i As Integer

            For i = 0 To lstAvailableLayers.SelectedItems.Count - 1
                ' Add only the selected layers to the right side list box
                lstLayersToUse.Items.Add(lstAvailableLayers.SelectedItems(i))
            Next
            For i = 0 To lstAvailableLayers.SelectedItems.Count - 1
                layerIds.Add(lt(lstAvailableLayers.SelectedItems(i)))
            Next
        End If
        vpLayertrans.Commit()
    End Sub

End Class

 This is the code that calls the form:

If diaTitleText.ShowDialog = System.Windows.Forms.DialogResult.OK Then
                                    layerIDs = diaTitleText.selectedLayers
                                    ' Freeze viewport layers.
                                    If Not vp = Nothing Then
                                        vp.FreezeLayersInViewport(layerIDs.GetEnumerator())
                                    End If

 Everytime I run it, it seems to be working, but layerIDs always says it equals nothing.

Can you see what's wrong?  I really do appreciate the time you've spent helping me.

Thanks,

Mark

Hi Art,

Thanks again, but somethings not working.  Here is my forms code now (the whole code):

Message 9 of 52
fieldguy
in reply to: mgorecki

This does not look right.  ReadOnly Property selectedLayers() As ObjectIdCollection

 

It looks like you are assigning an array() to an objectidecollection.

 

Try "ReadOnly Property selectedLayers As ObjectIdCollection".

Message 10 of 52
mgorecki
in reply to: fieldguy

Hi, I try to remove the parenthesis, but they keep reappearing every time I move the cursor off that line.

 

Thanks,
Mark

Message 11 of 52
mgorecki
in reply to: mgorecki

I've used it elsewhere in another form in this program to return a string:

ReadOnly Property newPageOption() As String
        Get
            Return pageOption
        End Get
    End Property

 And that one works just great.

Message 12 of 52
Anonymous
in reply to: mgorecki

 

I looked real quick and Not sure why you would create a Read-only property when it returns a public field that you can directly access and change?

 

I am not sure what you are doing but is layerids ever intialized?

 

Dim layerIds As ObjectIdCollection = new ObjectIdcollection()

Message 13 of 52
Anonymous
in reply to: Anonymous

 

A string will intialize to "" if you do not yourself

Message 14 of 52
mgorecki
in reply to: Anonymous

Hi Jeff,

Yes I declared it just before I did the ShowDialog.

If textTitle <> "" Then
                                ' After all of the attributes in the block have been checked and the viewport identified
                                Dim diaTitleText As New dialogTitleText(textTitle, textDieSide)
                                Dim layerIDs As ObjectIdCollection
                                If diaTitleText.ShowDialog = System.Windows.Forms.DialogResult.OK Then
                                    layerIDs = diaTitleText.selectedLayers

 Does it need to be:

Dim layerIds As ObjectIdCollection = new ObjectIdcollection()

 

Thanks,

Mark

Message 15 of 52
Anonymous
in reply to: mgorecki

From what you posted it looks like the code in move button is the only place that layerids has any items added.

 

Where and when does layerids have anything added?

Message 16 of 52
mgorecki
in reply to: Anonymous

layerIDs only has things added in the btnMoveLayers_Click sub.

Message 17 of 52
mgorecki
in reply to: mgorecki

Here is the module that calls the form.  It uses layerIDs in the replaceTitleText sub about halfway down.

Message 18 of 52
mgorecki
in reply to: mgorecki

I just used the Readonly property because I had success with it before.  I just want to be able to send the layerIDs ObjectIdCollection from the form to the code that called the form.  If there is another way (that will actually work) then I'm all for it.

 

Mark

Message 19 of 52
Anonymous
in reply to: mgorecki

Maybe add method to form that returns a collection of strings that are layer names, and in the calling code you can get the ObjectIds from there.

 

 

    Public Function GetSelectedLayerNames() As List(Of String)

        Dim objcoll(ListBox1.SelectedItems.Count) As Object
        Dim layerNames As New List(Of String)
        ListBox2.SelectedItems.CopyTo(objcoll, 0)
        layerNames.AddRange(objcoll)
        Return layerNames

    End Function

 

 

 

Message 20 of 52
chiefbraincloud
in reply to: mgorecki

It looks like you need a vacation Jeff.  I would have thought you would catch this one.

 

In the very first line of the class, you (not you Jeff, the OP) declared layerIds as an ObjectIdCollection.

 

Then in btnMoveLayers_Click, you declared another layerIds as New ObjectIdCollection, and added items to it, but this is not adding items to your class level variable, and the collection that is getting all the items added to it falls out of scope when the btnMoveLayers_Click function ends, and so is not accessible when the code returns to the calling function and tries to use it.

 

What I would do is add the New keyword to the declaration at the top of the Class (Dim layerIds as NEW ObjectIdCollection), and remove the declaration of layerIds from the click method.  Doing so will mean that when the layerIds are accessed by the calling function, the collection will never be nothing, but in the event of failure, may have a count of zero.

 

Alternatively, you could keep the top declaration the same, and change the line in the click method to:

 

layerIds = New ObjectIdCollection instead of Dim layerids as ....

 

this will mean that in the event of a failure prior to adding any layerIds, the collection will be Nothing, instead of a Zero Count.

Dave O.                                                                  Sig-Logos32.png

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost