I have implemented a command to draw a Plant3D pipe and it works fine when called from the CAD command prompt. When I call the same function from a button implemented in a a palette control behind a button then it fails.
Is there something special to do when calling something behind the button of a control?
Solved! Go to Solution.
Solved by ActivistInvestor. Go to Solution.
"Fails" is not a terribly-informative description of what's happening.
How does it fail?
Is there an exception? If so, what's the exception/message ?
Is there a stack trace when run in the debugger?
Your code is most-likely failing when called from a modeless UI element's click handler because it executes in the Application context, whereas when you run it from a registered command, it runs in the Document context. There are restrictions on what you can do from the application context. First, you must lock the document before you can make changes to it. You also cannot use the Editor's Command() method from the application context. The easiest solution is to run your code in the document context. To do that, you can use the ExecuteInDocumentContextAsync() method. See the example I posted in this thread for more about how it's used.
thanks ... it does solve the problem.
What about if I create a toolbar or tool pallet and keep the logic behind that. How will they behave... I mean they will execute in application context or doc context ?
Regards
Salman
You can define a custom UI element that has a Click event and an overridable OnClick() member, and implement the functionality in a reusable manner, similar to this:
public class CommandButton : Button
{
/// <summary>
/// No AutoCAD types should appear in this method
/// if it can be jitted at design-time:
/// </summary>
protected override void OnClick()
{
// Only run the Invoke() method if
// the code is running in AutoCAD:
if(!IsDesigning)
Invoke(base.OnClick);
}
// set to true if code is not running in IDE:
internal static readonly bool IsDesigning =
!Process.GetCurrentProcess().MainModule.FileName.ToUpper().StartsWith("AC");
/// <summary>
/// OK for AutoCAD types to appear here,
/// since it will never be jitted at design-time.
/// Ideally, this would live in another helper class:
/// </summary>
static void Invoke(Action action)
{
var docmgr = Application.DocumentManager;
if(docmgr.IsApplicationContext)
{
docmgr.ExecuteInCommandContextAsync(_ =>
{
action();
return Task.CompletedTask;
}, null);
}
else
{
action();
}
}
}
With the above, the event handler for the Click event will run in the document context, without having to do anything special.
See this thread, and this file for a better way to reuse the functionality I included in the example CommandButton class (which in retrospect, isn't really the best way to do it). The code I linked to allows the functionality to be reused when binding UI elements to ICommands.
Can't find what you're looking for? Ask the community or share your knowledge.