TeklaAppExtension is a template for creating Tekla Structures add-ins that integrate with Assistant. This template provides a foundation for building MVVM-based Tekla applications with a modern UI using WPF-UI.
Create a new Extension by selecting the template "Tekla App Extension for Assistant"

The template is organized according to the MVVM pattern:
The application starts with TeklaAppExtensionCommand.cs, which implements the ITeklaExtension<T> interface. The Run method is the entry point:
public IExtensionResult Run(ITeklaExtensionContext context, TeklaAppExtensionArgs args, CancellationToken cancellationToken)
{
// Create a service provider with all required services registered
var provider = ServiceFactory.Create(services =>
{
services.RegisterAppServices(args);
});
// Get the handle of the current process main window (Tekla Structures)
var handle = Process.GetCurrentProcess().MainWindowHandle;
// Show the application main window
WindowHandler.ShowWindow<MainWindow>(provider, handle);
// Return a result indicating success
return Result.Text.Succeeded("App started");
}
Initial user inputs are handled through the TeklaAppExtensionArgs class:
public class TeklaAppExtensionArgs
{
public string InitialComment { get; set; } = "Default comment";
}
This class can be extended with additional properties to capture different types of user input for your application. Properties in this class are automatically parsed into UI elements in the Extension Task configuration in Assistant.
Dependencies are registered in the Registrations.cs file using the .NET Dependency Injection framework. The template uses a RegisterAppServices extension method on IServiceCollection to configure all required services:
public static IServiceCollection RegisterAppServices(this IServiceCollection services, TeklaAppExtensionArgs args)
{
// Register user arguments
services.AddSingleton(args);
// Register view models
services.AddSingleton<MainWindow>();
services.AddSingleton<HomeViewModel>();
services.AddSingleton<AboutViewModel>();
// Register the Tekla service
services.AddSingleton<ITeklaService, TeklaService>();
return services;
}
When adding new view models or services:
RegisterAppServices methodservices.AddSingleton<IMyService, MyService>()Views and ViewModels are connected through data templates in ViewBindings.xaml:
<ResourceDictionary>
<DataTemplate DataType="{x:Type viewModels:HomeViewModel}">
<views:HomeView />
</DataTemplate>
<DataTemplate DataType="{x:Type viewModels:AboutViewModel}">
<views:AboutView />
</DataTemplate>
</ResourceDictionary>
This approach enables:
When adding a new view and view model:
The template follows a specific pattern for view models:
All view models inherit from ViewModelBase which provides common functionality:
Get<T>() and Set(value) methodsDo(Action method) methodsWhen(value)Example from HomeViewModel:
// Command to get the current model name
public IFluentCommand GetModelNameCommand => Do(GetName);
// Command with conditional execution
public IFluentCommand SetCommentOnSelectedElementsCommand =>
Do(SetCommentOnSelected)
.If(() => !string.IsNullOrEmpty(Comment)); // Only enabled when Comment is not empty
// The implementation method
private async Task SetCommentOnSelected(CancellationToken cancellationToken)
{
try
{
// Ensure Comment is not null before passing to the service
string comment = Comment ?? string.Empty;
int objectCount = _teklaService.SetCommentOnSelectedObjects(comment, cancellationToken);
if (objectCount > 0)
_snackbarService.Show("Success", $"Comment set on {objectCount} object(s).", ControlAppearance.Success);
else
_snackbarService.Show("Information", "No objects were selected.", ControlAppearance.Info);
}
catch (OperationCanceledException)
{
// User clicked the Cancel button. Re-throw OperationCanceledException exception to be handled by the MVVMFluent framework.
throw;
}
catch (Exception ex)
{
await _contentDialogService.ShowAlertAsync("Error",
$"An error occurred while setting the comment: {ex.Message}", "OK");
}
}
The template provides a robust property system that supports change notification and command interactions:
Get<T>() - Retrieves a property value from the view model's internal storageSet(value) - Sets a property value and raises change notificationWhen(value) - Begins a fluent API chain for more complex property updatesNotify(command) - Notifies a command that it should re-evaluate its executable stateSet() - Completes the property setting operation (used at end of a chain)// Simple property with basic change notification
public string? CurrentDocumentTitle
{
get => Get<string?>();
set => Set(value);
}
// Advanced property with command notification
public string? Comment
{
get => Get<string?>();
set => When(value) // Start a property update chain
.Notify(SetCommentOnSelectedElementsCommand) // Notify the command
.Set(); // Complete the property update
}
The TeklaService class provides methods for interacting with the Tekla Structures API. It implements cancellation support for long-running operations:
public class TeklaService : ITeklaService
{
// Get the name of the current Tekla model
public string GetModelName()
{
var model = new Model();
return model.GetInfo().ModelName;
}
// Delete all selected objects in the Tekla model
public int DeleteSelectedObjects()
{
var model = new Model();
var selector = new Tekla.Structures.Model.UI.ModelObjectSelector();
var selectedObjects = selector.GetSelectedObjects();
int objectCount = 0;
while (selectedObjects.MoveNext())
{
if (selectedObjects.Current != null && selectedObjects.Current.Delete())
objectCount++;
}
model.CommitChanges();
return objectCount;
}
// Set a comment on selected objects
public int SetCommentOnSelectedObjects(string comment, CancellationToken cancellationToken)
{
var model = new Model();
var selector = new Tekla.Structures.Model.UI.ModelObjectSelector();
var selectedObjects = selector.GetSelectedObjects();
int objectCount = 0;
while (selectedObjects.MoveNext())
{
if (selectedObjects.Current != null)
{
cancellationToken.ThrowIfCancellationRequested();
// Set the user property and modify the object if successful
if (selectedObjects.Current.SetUserProperty("comment", comment))
{
selectedObjects.Current.Modify();
objectCount++;
}
}
}
model.CommitChanges();
return objectCount;
}
}
This template utilizes the WPF UI framework, a modern UI library that follows the Windows 11 design language.
To learn more about the WPF UI framework and its capabilities:
The template provides a fluent API for creating commands through the IFluentCommand interface with extension methods that support method chaining:
Do(Action method) - Creates a command that executes a simple actionIf(Func<bool> condition) - Adds a condition that must be true for the command to executeHandle(Func<Exception, Task> handler) - Specifies how to handle exceptionspublic IFluentCommand SetCommentOnSelectedElementsCommand =>
Do(SetCommentOnSelected)
.If(() => !string.IsNullOrEmpty(Comment)) // Only execute if condition is true
.Handle(async ex => await HandleException(ex)); // Error handling
Separation of Concerns
Dependency Injection
Registrations.csMVVM Pattern
Error Handling
TeklaAppExtensionArgs if neededRegistrations.csViewBindings.xaml if neededUse Visual Studio Code's Run and Debug view to start or attach the debugger:
Launch In Design Mode
Launch In Design Mode configuration in .vscode/launch.json.-c Design argument (bin/Design/TeklaAppExtension.exe).Attach to Tekla
Attach to Tekla configuration in .vscode/launch.json.The template includes configuration for multiple Tekla Structures versions. Use the appropriate configuration for your target Tekla version:
The Azure Pipelines configuration in azure-pipelines.yml automatically builds and packages the extension for all configured Tekla versions.
This template includes the following features for demonstration purposes:
The application allows users to retrieve and display information about the current Tekla model. The home screen provides a button to get the active model's name.
Users can apply comments to selected objects in Tekla Structures:
The application provides visual feedback through notifications when comments are successfully applied.
The application offers a button to delete selected objects from the Tekla model with proper error handling and user feedback.
The application includes a navigation system with:
For all operations, the application provides:
The application can receive initial input at startup through the TeklaAppExtensionArgs class. In this template, a pre-populated comment field is available as an example.