Author Topic: Set default layer on close drawing  (Read 2276 times)

0 Members and 1 Guest are viewing this topic.

latour_g

  • Newt
  • Posts: 184
Set default layer on close drawing
« on: September 26, 2018, 11:02:24 AM »
Hi all,
I'm doing something wrong but I don't know what ! What I want do to is to set a default layer (in this case layer 0) on several close documents.  It does put the good  layer but in the ribbon, the layer is blank (see image). 

Here is my code :
Code - C#: [Select]
  1. private void btnTraiter2_Click(object sender, EventArgs e)
  2. {
  3.     bool Ok2Continue = true;
  4.  
  5.     for (int i = 0; i < dwgLst.Count; i++)
  6.     {
  7.         Database db = new Database(false, true);
  8.         using (db)
  9.         {
  10.             string fileName = dwgLst.GetKey(i).ToString();
  11.  
  12.             try { db.ReadDwgFile(fileName, FileShare.ReadWrite, false, ""); }
  13.  
  14.             catch (Autodesk.AutoCAD.Runtime.Exception ex) { Ok2Continue = false; }
  15.  
  16.             if (Ok2Continue)
  17.             {
  18.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  19.                 {
  20.                     listLayerID = listDWGLayerID[fileName];
  21.                     ObjectId id = ObjectId.Null;
  22.                     if (listLayerID.ContainsKey("0")) id = listLayerID["0"];
  23.                     db.Clayer = id;
  24.                     tr.Commit();
  25.                 }
  26.             }
  27.  
  28.             try { db.SaveAs(fileName, true, db.OriginalFileVersion, db.SecurityParameters); }
  29.             catch { MessageBox.Show("Error", "Error"); }
  30.         }
  31.         db.Dispose();
  32.     }
  33. }
  34.  

I have check with debug mode to make sure I apply a valid layer ID and it does. 
It should work because everything was working fine but then I made some change and it doesn't work now !
It was even working for all other properties such as textstyle, leaderstyle, dimstyle ... 

Thanks for your precious help !
« Last Edit: September 26, 2018, 12:06:28 PM by latour_g »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Set default layer on close drawing
« Reply #1 on: September 26, 2018, 11:11:04 AM »
Hi,

It looks like you do not Commit the transaction.
Speaking English as a French Frog

latour_g

  • Newt
  • Posts: 184
Re: Set default layer on close drawing
« Reply #2 on: September 26, 2018, 11:58:45 AM »
My mistake, the code was very long so I made a short version of it, I forgot to keep that line.  I do commit the transaction. I will correct my original post.
 

Atook

  • Swamp Rat
  • Posts: 1029
  • AKA Tim
Re: Set default layer on close drawing
« Reply #3 on: September 26, 2018, 12:45:46 PM »
Does it work if you use the TransactionManager from the mdiActiveDocument instead of the Database object?
Code - C#: [Select]
  1. Application.DocumentManager.MdiActiveDocument.TransactionManager.StartTransaction()
« Last Edit: September 26, 2018, 12:51:19 PM by Atook »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Set default layer on close drawing
« Reply #4 on: September 26, 2018, 01:17:43 PM »
Try changing the working database at each loop.

Code - C#: [Select]
  1.         private void btnTraiter2_Click(object sender, EventArgs e)
  2.         {
  3.             // store the current working database
  4.             var currentWorkingDb = HostApplicationServices.WorkingDatabase;
  5.  
  6.             for (int i = 0; i < dwgLst.Count; i++)
  7.             {
  8.                 using (Database db = new Database(false, true))
  9.                 {
  10.                     string fileName = dwgLst.GetKey(i).ToString();
  11.  
  12.                     try
  13.                     {
  14.                         db.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, false, "");
  15.  
  16.                         using (Transaction tr = db.TransactionManager.StartTransaction())
  17.                         {
  18.                             listLayerID = listDWGLayerID[fileName];
  19.                             ObjectId id = ObjectId.Null;
  20.                             if (listLayerID.ContainsKey("0")) id = listLayerID["0"];
  21.                             // set the side database as working database
  22.                             HostApplicationServices.WorkingDatabase = db;
  23.                             db.Clayer = id;
  24.                             tr.Commit();
  25.                         }
  26.  
  27.                         db.SaveAs(fileName, true, db.OriginalFileVersion, db.SecurityParameters);
  28.                     } // <- db is disposed here
  29.  
  30.                     catch { MessageBox.Show("Error", "Error"); }
  31.                 }
  32.                
  33.                 // restor the working database
  34.                 HostApplicationServices.WorkingDatabase = currentWorkingDb;
  35.             }
  36.         }

PS: I removed some useless instructions from your code
Speaking English as a French Frog

latour_g

  • Newt
  • Posts: 184
Re: Set default layer on close drawing
« Reply #5 on: September 26, 2018, 01:37:04 PM »
Hi Atook,
Thanks for your answer. It still do the same thing.

Hi Gile,
Thanks for your answer.  I'm getting an error.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: Set default layer on close drawing
« Reply #6 on: September 26, 2018, 01:51:49 PM »
It looks like you're using a list of ObjectIds (listLayerID) for each file this is not reliable and is probably why you get this error.
ObjectIds are unique identifiers in the session but they are non persistant between session (they're built to be unique when the database is created).
You should use the layer name instead and get the newly created ObjectId with: db.layerTable[layerName].
« Last Edit: September 27, 2018, 07:08:05 AM by gile »
Speaking English as a French Frog

Atook

  • Swamp Rat
  • Posts: 1029
  • AKA Tim
Re: Set default layer on close drawing
« Reply #7 on: September 26, 2018, 02:43:54 PM »
I'm also confused why you create a new database, check it for readall/share, then switch to the working database when you set the layer.

Why not work with the working database the entire time?

For what it's worth, here's the code I use to set a layer in the active database
Code - C#: [Select]
  1. /// <summary>
  2. /// Sets layer current, creates it if it doesn't exist
  3. /// </summary>
  4. /// <param name="layerName">Name of the layer.</param>
  5. /// <param name="color">The color.</param>
  6. /// <param name="print">whether the created layer is to be printed</param>
  7. /// <returns>True if the layername is valid, false if it's not</returns>
  8. public static bool SetLayer(string layerName, short color=7, bool print=true)
  9. {
  10.         if (IsValidSymbolName(layerName))
  11.         {
  12.                 ObjectId layID = ObjectId.Null;
  13.                 using (Transaction tr = Active.Document.TransactionManager.StartTransaction())
  14.                 {
  15.                         LayerTable layerTable = (LayerTable)tr.GetObject(Active.Database.LayerTableId, OpenMode.ForRead);
  16.                         if (!layerTable.Has(layerName))
  17.                         {
  18.                                 LayerTableRecord newLayer = new LayerTableRecord
  19.                                 {
  20.                                         Name = layerName,
  21.                                         Color = Color.FromColorIndex(ColorMethod.ByAci, color),
  22.                                         IsPlottable = print
  23.                                 };
  24.                                 layerTable.UpgradeOpen();
  25.                                 layID=layerTable.Add(newLayer);
  26.                                 tr.AddNewlyCreatedDBObject(newLayer, true);
  27.                         }
  28.                         else
  29.                         {
  30.                                 layID = layerTable[layerName];
  31.                         }
  32.                         LayerTableRecord layerRecord = (LayerTableRecord) tr.GetObject((layerTable[layerName]), OpenMode.ForWrite);
  33.                         if (layerRecord.IsFrozen)
  34.                         {
  35.                                 layerRecord.IsFrozen = false;
  36.                         }                      
  37.                         try
  38.                         {
  39.                                 Active.Database.Clayer = layID;
  40.                         }
  41.                         catch (System.Exception e)
  42.                         {
  43.                                 AID_Application.HandleError(e);
  44.                         }
  45.                         tr.Commit();
  46.                 }
  47.         }
  48.         else
  49.         {
  50.                 Active.WriteMessage("\nInvalid Layername: "+layerName);
  51.         }
  52.         return IsValidSymbolName(layerName);
  53. }
  54.  

where Active.Document is the mdiActiveDocument

latour_g

  • Newt
  • Posts: 184
Re: Set default layer on close drawing
« Reply #8 on: September 26, 2018, 02:58:34 PM »
Gile, so much easier and it's working fine now ! Thank you !
Atook, I'm not used to work with close dwg, I thought it was the way to go.  Thank for your code and your help !