Keep logic and user interface separate
It is very important to have a clear interface between the presentation logic (user interface) and the business logic. Do not mix these two types of logic.
- Do not implement any functionality or Open API calls in the form code (=UI thread). Form should be just a dialog.
- If you still do, do it asynchronously and be prepared for unexpected problems.
Explanation of the following code example
A plug-in contains a Pick button allowing the user to pick a point. However, when the pick is begun, Tekla Structures hangs.
This is caused by using the Picker from UI thread that causes deadlock. When Picker is executed in core, all child windows (including the plug-in dialog) lose focus. However, now the plug-in is calling Tekla Structures synchronously, and a deadlock appears. This can be solved by calling Picker in an asynchronized fashion.
public delegate void AsyncCaller();
// The callback method must have the same signature as the
// AsyncCallback delegate.
private void RefreshOriginPoint(IAsyncResult ar)
{
try
{
// Retrieve the delegate and handle result.
AsyncResult result = (AsyncResult)ar;
AsyncCaller caller = (AsyncCaller)result.AsyncDelegate;
caller.EndInvoke(ar);
if (originPoint != null)
{
OriginX.Text = Math.Round(originPoint.X, 6).ToString();
OriginY.Text = Math.Round(originPoint.Y, 6).ToString();
OriginZ.Text = Math.Round(originPoint.Z, 6).ToString();
}
}
catch { }
}
private void PickPoint()
{
Tekla.Structures.Model.UI.Picker modelPicker = new
Tekla.Structures.Model.UI.Picker();
try
{
originPoint = modelPicker.PickPoint("Pick the origin point");
}
finally
{
this.Enabled = true;
}
}
private void PickOrigin_Click(object sender, EventArgs e)
{
this.Enabled = false;
AsyncCaller ac = new AsyncCaller(this.PickPoint);
IAsyncResult result = ac.BeginInvoke(new AsyncCallback(RefreshOriginPoint),null);
}
Example application
For an example how to keep logic and user interface separate, take a look DimensionCreator code example that creates different types of dimensions.