Tekla Open API UI design with WPF
Windows Presentation Foundation (WPF) allows you to develop applications with modern user interface.
If you have previously built your Tekla Open API applications with Windows Forms, the fundamental WPF programming experience should be familiar.
WPF support available in Tekla Open API
The following WPF support is available in Tekla.Structures.Dialogs starting from Tekla Open API version 2018:
New WPF base classes for application and plugin dialogs
-
ApplicationWindowBase (apps)
-
PluginWindowBase (plugins)
New user interface controls
-
Filtering check box
-
Ok, Apply, Modify, Get, Cancel
-
Save Load attributes
-
Catalogs
New StructuresDialogAttribute
-
For connecting dialog attributes in view model to data storage
Get started by inheriting from WPF base class
- Inherit your plugin dialog from WPF base class PluginWindowBase.
- Add your view model class to constructor. System will create datastorage based on it.
public partial class MainWindow : PluginWindowBase { private MainWindowViewModel dataModel; public MainWindow(MainWindowViewModel DataModel) { InitializeComponent(); dataModel = DataModel; } // define event handlers for buttons… }
- Inherit your application dialog from WPF base class ApplicationWindowBase.
- Add view model class to datacontext and initialize data model storage with it.
public partial class MainWindow : ApplicationWindowBase { MainWindowViewModel viewModel = new MainWindowViewModel(); public MainWindow() { InitializeComponent(); this.DataContext = viewModel; this.InitializeDataStorage(viewModel); if(this.GetConnectionStatus()) { InitializeDistanceUnitDecimals(); } }
Create view model class for dialog attributes
- Create needed fields and properties for dialog data.
- Bind dialog data to Tekla Structures data attributes with StructuresDialog custom attribute: name and type of attribute in data storage.
public class MainWindowViewModel : INotifyPropertyChanged { private string partname = string.Empty; [StructuresDialog("name",typeof(TD.String))] public string Partname { get { return partname; } set { partname = value; OnPropertyChanged("Partname"); } }
- Add PropertyChanged event handler for refreshing dialog values when view model property changes.
public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string property) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(property)); } }
Dialog definition with XAML
- Add needed class, namespace and control definitions in XAML.
-
<tsd:PluginWindowBase x:Class="TeklaWPFPlugin.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:tsd="clr-namespace:Tekla.Structures.Dialog;assembly=Tekla.Structures.Dialog" xmlns:local="clr-namespace:TeklaWPFPlugin" xmlns:UIControls="clr-namespace:Tekla.Structures.Dialog.UIControls;assembly=Tekla.Structures.Dialog"
Add needed UI controls to dialog.
-
Title localization
-
Bind TextBox to view model property
-
Filterbox with attribute binding
-
Label with localizable content
-
Saveload control
Title="{tsd:Loc albl_Test_plugin}" Height="355" Width="590" HorizontalAlignment="Stretch"> <Grid HorizontalAlignment="Stretch" Margin="0,0,0,0"> <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="159,74,0,0" TextWrapping="Wrap" Text="{Binding Partname, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/> <UIControls:WpfFilterCheckBox HorizontalAlignment="Left" Margin="136,78,0,0" VerticalAlignment="Top" AttributeName="name"/> <Label x:Name="label" Content="{tsd:Loc albl_Part_name}" HorizontalAlignment="Left" Margin="20,71,0,0" VerticalAlignment="Top" Height="30" Width="100"/> <UIControls:WpfSaveLoad HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Top" Height="51" />
-
-
Add needed UI controls.
-
Button row for Ok, Apply, Modify, Get, and Cancel buttons.
-
Add events for button clicks.
<UIControls:WpfOkApplyModifyGetOnOffCancel HorizontalAlignment="Stretch" Margin="0,150,0,0" VerticalAlignment="Bottom" Height="51" ApplyClicked="WPFOkApplyModifyGetOnOffCancel_ApplyClicked" CancelClicked="WPFOkApplyModifyGetOnOffCancel_CancelClicked" GetClicked="WPFOkApplyModifyGetOnOffCancel_GetClicked" OkClicked="WPFOkApplyModifyGetOnOffCancel_OkClicked" OnOffClicked="WPFOkApplyModifyGetOnOffCancel_OnOffClicked" ModifyClicked="WPFOkApplyModifyGetOnOffCancel_ModifyClicked"/> </Grid> </tsd:PluginWindowBase>
-
Add user interface class for plugin
Add user interface definition using WPF class in plug-in source.
[PluginUserInterface("TeklaWPFPlugin.MainWindow")]
Create localization file (*.ail)
Default file name is based on assembly name containing the WPF dialog.
Additional files can be added normally using dialogs Localization class.
Add catalog control
Steps needed to add a catalog control to WPF dialog are similar as with forms:
-
Drag a catalog control to dialog.
-
Drag a textbox to show the data.
-
Add needed events for catalog control.
-
Connect catalog control to your view model data in event handlers.
The XAML could look like this:
<TextBox x:Name="textBox_Copy" HorizontalAlignment="Left" Height="23" Margin="159,112,0,0" TextWrapping="Wrap" Text="{Binding Profilename, Mode=TwoWay}" VerticalAlignment="Top" Width="120"/>
<UIControls:WpfProfileCatalog x:Name="profileCatalog" HorizontalAlignment="Left" Margin="312,111,0,0" VerticalAlignment="Top" SelectClicked="profileCatalog_SelectClicked" SelectionDone="profileCatalog_SelectionDon
View model:
[StructuresDialog("profile", typeof(TD.String))]
public string Profilename
{
get { return profile; }
set { profile = value; OnPropertyChanged("Profilename"); }
}
Event handling:
private void profileCatalog_SelectClicked(object sender, EventArgs e)
{
this.profileCatalog.SelectedProfile = this.dataModel.Profilename;
}
private void profileCatalog_SelectionDone(object sender, EventArgs e)
{
this.dataModel.Profilename = this.profileCatalog.SelectedProfile;
}