I posted about this issue previously: opening-a-drawing-in-the-background-copying-a-layout-and-saving
I have constructed a more confined funnel to where the issue is lying.
The problem that I am having is that my viewports keep resetting.
I have noticed that this happens based on the context that I save and close my document in.
When I am talking about the order, I am referring to the order in which the Layouts are presented in an opened document:
[Model] [Layout1] [Layout2] [Layout3] [Layout4]
If I Save and Close the document on the Layout I am deleting [Layout4], the Layout before it receives this reset[Layout3].
If I Save and Close the document on the Layout before the one I am deleting [Layout3], that layout gets this reset [Layout3].
If I Save and Close the document on a random layout, say 3 layouts before the one I am deleting [Layout1], that layout gets this reset [Layout1].
If I Save and Close in Model Space, then nothing gets reset.
Here is the code that is using the LayoutManager and where I highly suspect is causing the viewport reset.
private void DeleteLayoutInDrawing(string LayoutName, string LayoutFileName)
{
Database OriginalDB = HostApplicationServices.WorkingDatabase;
try
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(LayoutFileName, System.IO.FileShare.ReadWrite, false, null);
HostApplicationServices.WorkingDatabase = db;
LayoutManager lm = LayoutManager.Current;
lm.DeleteLayout(LayoutName);
db.SaveAs(LayoutFileName, DwgVersion.Current);
HostApplicationServices.WorkingDatabase = OriginalDB;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I was wondering if anyone has some thoughts on what is causing this.
I had this function in a transaction, and it still produced the same issue.
I have tried to set the CurrentLayout for the LayoutManager to "Model" but I dont think it was working. If someone know how I could do this. I feel like setting the CurrentLayout to ModelSpace would allow me to do the deletion without breaking anything.
This was happening in another instance that I was using LayoutManager, so I am hoping in fixing this, I can transfer that fix onto the other function.
Thank you!
Solved! Go to Solution.
Solved by Poncho_Slim. Go to Solution.
Solved by Poncho_Slim. Go to Solution.
Solved by Poncho_Slim. Go to Solution.
This is driving me insane. I have tried everything.
Here is my current code, and it is still not working. Now saving and closing on the layout I am deleting does not Reset any other layout, but if I save and close on any other layout besides Model, it Resets that layout that I closed on. I've attempted to set the LayoutManager to Model space which stopped the bug happening for when I save and close on the layout I am deleting, but it is still doing this for the case that I described.
I really need some help on this.
private void DeleteLayoutInDrawing(string LayoutName, string LayoutFileName)
{
Database OriginalDB = HostApplicationServices.WorkingDatabase;
try
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(LayoutFileName, System.IO.FileShare.ReadWrite, false, null);
HostApplicationServices.WorkingDatabase = db;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
// Look through layouttable
DBDictionary layoutDict = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
foreach (DBDictionaryEntry entry in layoutDict)
{
if (entry.Key == "Model")
{
LayoutManager lm = LayoutManager.Current;
MessageBox.Show($"{lm.CurrentLayout}\n{lm.LayoutCount}");
lm.SetCurrentLayoutId(entry.Value);
MessageBox.Show($"{lm.CurrentLayout}\n{lm.LayoutCount}");
if(lm.LayoutExists(LayoutName))
{
MessageBox.Show($"{lm.CurrentLayout}\n{lm.LayoutCount}");
lm.DeleteLayout(LayoutName);
lm.SetCurrentLayoutId(entry.Value);
MessageBox.Show($"{lm.CurrentLayout}\n{lm.LayoutCount}");
db.SaveAs(LayoutFileName, DwgVersion.Current);
break;
}
}
}
}
HostApplicationServices.WorkingDatabase = OriginalDB;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Why is your code calling Database.SaveAs() repeatedly inside of a foreach() Loop that iterates over each layout in the database? That does not make any sense at all.
So I followed the logic of there only being one model space, and if that model space is found, then the function does some work, and then Saves the database. This can only happen once since it then breaks out of the loop afterwards.
I still do not understand the purpose of writing the loop and breaking out when you reach the model space layout. If. your objective is to simply delete a layout having a given name you don't need to write a loop you just get the object ID of that layout and delete it. You may have to set another layout to the current layout if that layout that you are deleting is the current layout but there's no need for a loop. I can't tell you if taking a more straightforward path to deleting the layout is going to solve the problem you're having.
I have found the bug!
The other place that was causing this error was in another function in the same routine.
Here is the broken function:
private void ClearRSandDateFromDeltas(string RS, string FullPath)
{
bool ModificationMadeModel = false;
bool ModificationMadePaper = false;
var OriginalDB = HostApplicationServices.WorkingDatabase;
using (var db = new Database(false, true))
{
db.ReadDwgFile(FullPath, System.IO.FileShare.ReadWrite, true, "");
db.CloseInput(true);
HostApplicationServices.WorkingDatabase = db;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Clear the RS and Date from the Deltas
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btrmodel = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
BlockTableRecord btrpaper = tr.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForRead) as BlockTableRecord;
ModificationMadeModel = ClearDeltaRSandDate(tr, ref btrmodel, RS, FullPath);
ModificationMadePaper = ClearDeltaRSandDate(tr, ref btrpaper, RS, FullPath);
if (ModificationMadeModel || ModificationMadePaper)
{
tr.Commit();
db.SaveAs(FullPath, DwgVersion.Current);
}
}
}
HostApplicationServices.WorkingDatabase = OriginalDB;
}
private bool ClearDeltaRSandDate(Transaction tr, ref BlockTableRecord btr, string RS, string FullPath)
{
bool ModificationMade = false;
foreach (ObjectId id in btr)
{
Entity ent = tr.GetObject(id, OpenMode.ForRead) as Entity;
if (ent is BlockReference)
{
BlockReference br = ent as BlockReference;
if (br.Name == ("FullDeltaBlock"))
{
foreach (ObjectId attributeID in br.AttributeCollection)
{
AttributeReference attRef = tr.GetObject(attributeID, OpenMode.ForRead) as AttributeReference;
if (attRef.TextString == $"RS-{RS}")
{
attRef.UpgradeOpen();
attRef.TextString = "";
ModificationMade = true;
Delta delta = new Delta();
delta.Handle = br.Handle.ToString();
delta.SelectViaDrawing(FullPath);
delta.RSSheet = 1;
foreach (ObjectId datesearchatt in br.AttributeCollection)
{
AttributeReference dateatt = tr.GetObject(datesearchatt, OpenMode.ForRead) as AttributeReference;
if (dateatt.Tag == "DATE")
{
dateatt.UpgradeOpen();
dateatt.TextString = "";
delta.Date = DateTime.Parse("2000-01-01");
}
}
delta.Update();
}
}
}
}
}
return ModificationMade;
}
When I closed in model space, no viewport would be reset. When I saved and closed on the sheet I am deleting, no viewport would be reset, due to the function that does the deleting moving into model space. But it would still do it when I saved and closed in any other sheet.
I eventually came to the conclusion that it was not due to the layout manager, but instead the Modifications I was doing in "ModelSpace" while my LayoutManager was on a Layout that is not model space, i.e I am in Paperspace doing model space things.
Here is the fixed code. I will continue to test it because I am afraid of if I have to do PaperSpace modifications for other cases, for example: If a block is placed in PaperSpace, and I want to modify it. But for this general base case, this worked!
private void ClearRSandDateFromDeltas(string RS, string FullPath)
{
bool ModificationMadeModel = false;
bool ModificationMadePaper = false;
var OriginalDB = HostApplicationServices.WorkingDatabase;
using (var db = new Database(false, true))
{
db.ReadDwgFile(FullPath, System.IO.FileShare.ReadWrite, true, "");
db.CloseInput(true);
HostApplicationServices.WorkingDatabase = db;
using (Transaction tr = db.TransactionManager.StartTransaction())
{
// Move the LayoutManager to the Model Space
DBDictionary layoutDict = tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
LayoutManager lm = LayoutManager.Current;
foreach (DBDictionaryEntry entry in layoutDict)
{
if (entry.Key == "Model")
{
lm.CurrentLayout = entry.Key;
break;
}
}
// Clear the RS and Date from the Deltas
BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
BlockTableRecord btrmodel = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForRead) as BlockTableRecord;
BlockTableRecord btrpaper = tr.GetObject(bt[BlockTableRecord.PaperSpace], OpenMode.ForRead) as BlockTableRecord;
ModificationMadeModel = ClearDeltaRSandDate(tr, ref btrmodel, RS, FullPath);
ModificationMadePaper = ClearDeltaRSandDate(tr, ref btrpaper, RS, FullPath);
if (ModificationMadeModel || ModificationMadePaper)
{
tr.Commit();
db.SaveAs(FullPath, DwgVersion.Current);
}
}
}
HostApplicationServices.WorkingDatabase = OriginalDB;
}
I hope this helps anyone running into this issue as it was such a weird issue that I could not find anything on here in the forums.
I further consolidated the ModelSpace. No need for all that tomfoolery
LayoutManager lm = LayoutManager.Current;
lm.CurrentLayout = "Model";
Here is the Updated DeleteLayout Function:
private void DeleteLayoutInDrawing(string LayoutName, string LayoutFileName)
{
Database OriginalDB = HostApplicationServices.WorkingDatabase;
try
{
using (Database db = new Database(false, true))
{
db.ReadDwgFile(LayoutFileName, System.IO.FileShare.ReadWrite, false, null);
HostApplicationServices.WorkingDatabase = db;
using(Transaction tr = db.TransactionManager.StartTransaction())
{
LayoutManager lm = LayoutManager.Current;
lm.CurrentLayout = "Model";
if (lm.LayoutExists(LayoutName))
{
lm.DeleteLayout(LayoutName);
lm.CurrentLayout = "Model";
db.SaveAs(LayoutFileName, DwgVersion.Current);
}
}
HostApplicationServices.WorkingDatabase = OriginalDB;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'd recommend that you add a finally block to your try/catch that has the statement
HostApplicationServices.WorkingDatabase = OriginalDB;
. . . just to be safe.
I assume you won't be deleting the last/only layout . . . but you may consider guarding against that happening.
Regards,
// Called Kerry in my other life.
Everything will work just as you expect it to, unless your expectations are incorrect.
class keyThumper<T> : Lazy<T>; another Swamper
Can't find what you're looking for? Ask the community or share your knowledge.