Change Current Layout

Change Current Layout

Anonymous
Not applicable
4,633 Views
9 Replies
Message 1 of 10

Change Current Layout

Anonymous
Not applicable

I have read many forums on this and I still can't figure out why my code crashes AutoCAD. Some things I can do so simply in LISP are crazy in C#...

 

 public static void SetCurrentLayoutTab(string tab)
        {
            using (DocumentLock lk = acDoc.LockDocument())
            {
                // Start a transaction in the new database
                using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
                {
                    try
                    {
                        LayoutManager.Current.CurrentLayout = tab;
                        acTrans.Commit();
                    }
                    catch
                    {

                        acTrans.Abort();

                    }
                }
            }
        }
0 Likes
Accepted solutions (1)
4,634 Views
9 Replies
Replies (9)
Message 2 of 10

_gile
Consultant
Consultant
Accepted solution

Hi,

 

This should work:

 

 

public static void SetCurrentLayoutTab(string tab)
{
    var doc = Application.DocumentManager.MdiActiveDocument;
    using (doc.LockDocument())
        LayoutManager.Current.CurrentLayout = tab;
}

 

Locking the document is only mandatory if the method is called in application context (CommandFlags.Session, modeless dialog, ...).

In document context, you can simply call:

 

LayoutManager.Current.CurrentLayout = tab;

 



Gilles Chanteau
Programmation AutoCAD LISP/.NET
GileCAD
GitHub

Message 3 of 10

ActivistInvestor
Mentor
Mentor

No need to start a transaction to use LayoutManager to change the current layout, and I don't seem to have any problem activating a layout by setting the CurrentLayout property, so regarding the comment in your code (Start a transaction in the new database)  what new database would that be?

 

Your code references the variables: acDoc and acCurDb, that aren't declared in the method. Are they static fields of your class? If so, I'll guess that's probably why your code is crashing.

 

Locking the document shouldn't have any role in a failure in this case, so you would only have to do that if your code is running in the application context, rather than from the handler of a registered command that doesn't use the CommandFlags.Session flag.

 

You should also display a message in the catch{} block displaying the exception information so you know what happened.

 


@Anonymous wrote:

I have read many forums on this and I still can't figure out why my code crashes AutoCAD. Some things I can do so simply in LISP are crazy in C#...

 

 public static void SetCurrentLayoutTab(string tab)
        {
            using (DocumentLock lk = acDoc.LockDocument())
            {
                // Start a transaction in the new database
                using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction())
                {
                    try
                    {
                        LayoutManager.Current.CurrentLayout = tab;
                        acTrans.Commit();
                    }
                    catch
                    {

                        acTrans.Abort();

                    }
                }
            }
        }

 

Message 4 of 10

kerry_w_brown
Advisor
Advisor

 

I'd have thought that if acDoc and acCurDb were not declared and assigned a value the compiler would throw a wobbly, rather than allow compilation and cause a runtime error.

 

 

added:

That being said, there a lot of questions on the forums that could be resolved more readily if a little bit more information was included with the original query.

 

Regards,

 

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 5 of 10

ActivistInvestor
Mentor
Mentor

@kerry_w_brown wrote:

 

I'd have thought that if acDoc and acCurDb were not declared and assigned a value the compiler would throw a wobbly, rather than allow compilation and cause a runtime error.

 

 

added:

That being said, there a lot of questions on the forums that could be resolved more readily if a little bit more information was included with the original query.

 

Regards,

 

 


I presumed that acDoc and acCurDb must be static members of the type that declares the method (or a containing type), as that's the only way it would compile, but wanted the pose the question to the OP anyway. The compiler wouldn't complain if the variables/static members aren't assigned a value, and that would trigger a runtime error, which is quite possibly what's going on, or the acDoc and/or acCurDb aren't the active document/database, since that's what the LayoutManager's methods operate on.

 

0 Likes
Message 6 of 10

Anonymous
Not applicable

I do have them as static members, but it hasn't caused this issue until now. Granted, I am not changing anything in CAD up until now. I understand that more information would have been useful, but I have a lot of code and this is just one small portion of it.

 

What about this is causing the crash?

 

        private static Editor ed = acDoc.Editor;

        //Returns the current autocad reference
        public static Document acDoc
        {
            get
            {
                return Application.DocumentManager.MdiActiveDocument;
            }
        }


        //returns the databse of the active autocad instance
        public static Database acCurDb
        {
            get
            {
                return acDoc.Database;
            }
        }
0 Likes
Message 7 of 10

ActivistInvestor
Mentor
Mentor

@Anonymous wrote:

I do have them as static members, but it hasn't caused this issue until now. Granted, I am not changing anything in CAD up until now. I understand that more information would have been useful, but I have a lot of code and this is just one small portion of it.

 

What about this is causing the crash?

 

        private static Editor ed = acDoc.Editor;

        //Returns the current autocad reference
        public static Document acDoc
        {
            get
            {
                return Application.DocumentManager.MdiActiveDocument;
            }
        }


        //returns the databse of the active autocad instance
        public static Database acCurDb
        {
            get
            {
                return acDoc.Database;
            }
        }

You can put a try{} catch{} block around the entire method body, and in the catch{} block, see what exception is being thrown (display it on the text window using exception.ToString()).

 

The one issue with the code above is that the Editor shouldn't be cached. You should just get it from the acDoc property when you need it, because if the active document changes, the value of the static field you assigned the Editor to doesn't change. Every Document has its own Editor that must be used when the Document is active.

 

You can change the static field to a property like this:

 

public static Editor ed
{
   get
   {
       return acDoc.Editor;
   }
}

If there is much more to your code, it may not be possible to tell you what is causing the crash without seeing more of the code.

Message 8 of 10

Anonymous
Not applicable

So, if I was calling it from a class other than my main class, would that be a possible reason for it throwing an exception?

0 Likes
Message 9 of 10

kerry_w_brown
Advisor
Advisor

zdraboin wrote:

So, if I was calling it from a class other than my main class, would that be a possible reason for it throwing an exception?



 

It depends on the value and scope of the variables.

 

You say "if I was ... " 

Does that mean you are ?

 

As mentioned several times in this thread, Implement error handling and perhaps be more forthcoming about your implementation.

 

Have you tried to debug/trace the code. ?

Have you made use of the Locals pane in Visual Studio when stepping through code ?

 


// Called Kerry or kdub in my other life.

Everything will work just as you expect it to, unless your expectations are incorrect. ~ kdub
Sometimes the question is more important than the answer. ~ kdub

NZST UTC+12 : class keyThumper<T> : Lazy<T>;      another  Swamper
0 Likes
Message 10 of 10

ActivistInvestor
Mentor
Mentor

@Anonymous wrote:

So, if I was calling it from a class other than my main class, would that be a possible reason for it throwing an exception?


As @kerry_w_brown says, it depends on what your main class may be doing in preparation for using the method, but it should be designed such that it could be called from any class, with the understanding that a document lock would be needed if the caller is running in the application context (e.g., from a click handler of a button on a PaletteSet or a modeless dialog, or a command method that has the CommandFlags.Session flag set).

 

You also aren't showing the calling context. Where is the method being called from? Is it being called from the handler of a CommandMethod or, a button-click handler on a form or window, or from the handler of some AutoCAD event (the latter of which is the most dangerous calling context).

 

Without knowing something about the calling context, no one can tell you why your code is failing.

 

The other problem is that you're not doing what you can to find out exactly what the cause of the exception is, which is to do something like this:

 

try
{
    // Code here that could throw an exception
}
catch(System.Exception ex)
{
    Application.DocumentManager.MdiActiveDocument.Editor.WriteMessage(ex.ToString());
}

 

 

0 Likes