Sunday, July 4, 2010

[Revit API] Document.PrintManager returns a new instance every time

A gotcha that you may run into if you use the Print API in Revit is that the PrintManager property of a Document always returns a NEW PrintManager.
So if you make a change (say to the print range) of Document.PrintManager directly, it will be pointless.
Document.PrintManager.PrintRange = PrintRange.Select;
//then submit print
Document.PrintManager.SubmitPrint(view);

both will act on a NEW PrintManager each time, which isn’t what you want. What you need to do is maintain a reference to PrintManager yourself, only calling Document.PrintManager once.
PrintManager manager = Document.PrintManager;
manager.PrintRange = PrintRange.Select;
manager.SubmitPrint(view);

If you have a look using Red Gate’s .NET Reflector to disassemble that method in the RevitAPI.dll, you can see why:
public unsafe PrintManager get_PrintManager()
{
    PrintManager manager;
    REVIT_MAINTAIN_STATE revit_maintain_state;
    REVIT_MAINTAIN_STATE.{ctor}(&revit_maintain_state);
    try
    {
        manager = new PrintManager(this);
    }
    fault
    {
        ___CxxCallUnwindDtor(REVIT_MAINTAIN_STATE.{dtor}, (void*) &revit_maintain_state);
    }
    REVIT_MAINTAIN_STATE.{dtor}(&revit_maintain_state);
    return manager;
}

As convenient as only passing around the Document object is, it’s not going to work! Changes made to one instance are not likely to apply to any others.