Getting started
In order to set up an application which uses classes of the Sartorius Application Foundation several preliminaries have to be satisfied. This section aims at explaining the basic steps to develop an application which can use the functionalities offered by the Sartorius Application Foundation. A WPF application which is based on the SAF requires registration and configuration during the application startup process — this is known as bootstrapping the application.
The following manual provides step-by-step instructions to create a simple WPF application which is based on the SAF. The aim of this manual is to introduce the minimum requirements for an application using the SAF. The implementation follows the design principles introduced in Concepts.
Prerequisites
Setting Build properties
Make sure that the following project configurations are made for any new project added to the solution:
In order to use the output directories created for storing the bins and the executable, the properties of all projects have to be set accordingly:
Click with the right mouse button on the project name in the Solution Explorer, choose "Properties". In the Application property make sure that the target framework is set to ".net Framework 4.5". Further, in the Build property change the Output path to "....\Deployment\Release" ("....\Deployment\Debug") for Configuration flavor "Release" ("Debug").
SAF packages
To ensure having the most actual SAF libraries an easy way is to use SAF Nuget Packages from the Sartorius Nuget Server. Another advantage of using the Nuget packages is that dependencies are resolved and the corresponding libraries are automatically downloaded and referenced.
- To use Sartorius NuGet packages, follow the instructions in the Add the Sartorius NuGet server tutorial.
- Optional step: It is possible to debug the SAF components, this is described in Tutorial Debug the SAF components.
Create your application
With the following set of steps all required projects and classes are created for your WPF application that is based on the SAF.
- Open visual studio
- Create a new solution with a solution name of your choice and a project name of your choice.
- Choose "Wpf Application" as component that is comprised in the project. The solution should be located in the "Source" folder created in the last section.
- Confirm with OK.
- Make sure that the following files exist in the project:
- appconfig.json (optional)
- MainWindow.xaml
- App.xaml
- Take care that the solution and all generated files are located in the Source folder. The MainWindow will currently not be used.
- Add a new class with name "AppInit" to the project. This is the entry point of the application:
- In the Solution Explorer click on the project with the right mouse button, choose "Add", choose "New Item…"
- In the window that opens select "Class"
- Rename the class to "AppInit.cs"
- Confirm with OK
Implementing the classes
Application configuration:
The application configuration file does not need to be changed. The application compiles without any version configurations.
App class (App.xaml and App.xaml.cs )
- In the following we create the necessary preconditions for the App class to be a SAF Wpf Application. Add the following NuGet package to the project
- Sartorius.SAF.Presentation.Application (Provides the definition of the Application class): Adding this package also installs Sartorius.SAF.Presentation.Application package the Sartorius.SAF.Presentation depends on.
- Replace the content in App.xaml and its code behind file by the following code. This xaml code defines the user control to be of type Application.
<SAF:Application x:Class="Main.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:SAF="http://www.sartorius.com/SAF"> </SAF:Application>
/// <summary> /// Interaction logic for App.xaml /// </summary> public class App { }
- In the following we create the necessary preconditions for the App class to be a SAF Wpf Application. Add the following NuGet package to the project
3 AppInit class This class defines two methods, "Run" and "CanClose". You can add initialization to the "Run" method, if your application needs any. Setting the MainWindow of the application here is no longer needed.
Note
Take care that the AppInit class is exported as instance of type IApp in order to make it available in the MEF container.
Running the application and analyzing the functionalities:
After building the application, in the deployment folder (Deployment/Debug or Deployment/Release) you find the executable. Starting the executable, a default MainWindow appears on the screen. This is not the MainWindow.xaml currently in your project. This one will be used later in the tutorials.
Because the application has been defined as a SAF Wpf Application following tools are supported out-of-the-box:
- Exception Handling
- MEF support
- SplashScreen
- Inversion of control
- Dependency injection
Further steps: add a module to the application
This section describes the principal composition of a composite application, i.e. an application that consists of several components that are loaded in the regions of the main view. Furthermore, it demonstrates how the MVVM pattern might be implemented supported by the SAF.
Create a new project in solution, in the following called "ModuleA":
- In the Solution Explorer click on the solution with the right mouse button, choose "Add", choose "New Project…"
- Choose "Class Library" as component that is comprised in the project.
- Rename the project to "Module"
- Confirm with OK
- Rename the class in the Module project to "ModuleInit.cs" and accept to globally change this name in all documents of this project
- See Section Setting Build properties to set the properties of the new project.
- Add a new class with name "HelloWorldViewModel" to the ModuleA project:
- In the Solution Explorer click on the Module project with the right mouse button, choose "Add", choose "New Item…"
- In the window that opens select "Class"
- Rename the class to "HelloWorldViewModel.cs"
- Confirm with OK
- Add a WPF user control to the ModuleA project:
- In the Solution Explorer click on the Module project with the right mouse button, choose "Add", choose "New Item…"
- In the window that opens select "User control (WPF)"
- Rename the user control to "HelloWorldView.xaml"
- Confirm with OK
Implement ModuleInit:
The ModuleInit class coordinates the activation of the module within the region it is assigned to. A simple module consists of a View and a ViewModel. The ModuleInit class also cares for setting the dataContext of the View to the corresponding ViewModel. The SAF offers the interface IModule and IApplicationMenuItem to complete these tasks.
Add the following references:
- Sartorius.SAF.Presentation NuGet package: defines the IModule interfaces and the IRegionManager extensions
- System.ComponentModel.Composition: used for importing/exporting properties
- System.Xaml: used for WPF controls The following example class implements the IModule and IApplicationMenuItem interfaces. Apart from describing properties this interface defines the method Initialize which can be used to initialize the module and the method OnActivate which should be used to activate the View (HelloWorldView) and the ViewModel (HelloWorldViewModel) that correspond to the module with the visualizing region.
Note
Make sure that the "Sartorius.SAF.Extensions" namespace is added as using to the module class. Otherwise the regionManager extension methods are not accessible.
/// <summary> /// initializes the greeting view in the content region of the application /// </summary> [ModuleExport("ModuleA", typeof(IModule))] public class ModuleInit : IModule, IApplicationMenuItem { private readonly IRegionManager regionManager; /// <summary> /// Constructs the ModuleInit. /// The Constructor has an ImportingConstructor attribute /// to inject dependencies via MEF. /// </summary> [ImportingConstructor] public ModuleInit(IRegionManager regionManager) { this.regionManager = regionManager; } /// <summary> /// Gets the display name of the module. /// </summary> public String Caption => "HelloWorld Module"; /// <summary> /// Gets the module description. /// </summary> public String Description => "This is a simple module to demonstrate how a modular application works."; /// <summary> /// Gets the icon shown in the application menu. /// </summary> public Object Icon { get; } /// <summary> /// Gets the source of the (preview) image shown in the application menu. /// </summary> public Uri ImageSource { get; } /// <summary> /// Activates the view when the application menu item is activated. /// </summary> public void OnActivate() { this.regionManager.RegisterViewWithRegion<HelloWorldView, HelloWorldViewModel>("MainRegion"); } /// <summary> /// Gets the module id. /// </summary> public String Id => "HelloWorldModule"; /// <summary> /// Indicates whether this module is enabled. /// </summary> /// <remarks> /// For security reasons, this property should be checked in the <see cref="M:Sartorius.SAF.Modularity.IModule.Initialize" /> implementation before executing any code. /// </remarks> public Boolean IsEnabled => true; /// <summary> /// Initialize the module /// </summary> public void Initialize() { // No initialization needed for this module. } }
Implement the "HelloWorldView" and "HelloWorldViewModel":
The following class examples define a view with it's logic. In the ModuleInit Initialize method the DataContext between the View and ViewModel is set and the View is activated. This means starting the application shows the HelloWorldView in the MainRegion.
<UserControl x:Class="Sartorius.SAF.Documentation.Examples.GettingStarted.Module.HelloWorldView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300"> <StackPanel Background="{DynamicResource SAF_BG_S25}"> <TextBlock Height="30" FontSize="24" HorizontalAlignment="Stretch" TextAlignment="Center" Text="{Binding Greeting}" Margin="0,0,0,20" Style="{DynamicResource SAF_TextBlock}" /> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <Label>Insert your name :</Label> <TextBox Height="30" Width="150" VerticalAlignment="Center" Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Style="{DynamicResource SAF_TextBox}" /> <Button Command="{Binding OK}" Width="80" Height="30" Content="OK" Style="{DynamicResource SAF_Button}" /> </StackPanel> </StackPanel> </UserControl>
Note
Take care to export the classes and to provide an importing constructor as well. Feel free to change the example code in the view and the ViewModel to experience other logic and tools the SAF provides.
Further steps: application configuration - example use specific skins in the application that are defined in the SAF
The SAF offers a lot of tools out-of-the-box that require configurations made in the application configuration file. The following list gives an overview:
- ExceptionHandling
- Skins: Design of the UI elements
- Settings: Storing and restoring of user-application settings and UI settings in a file or in the SAF Database
- Defines values for application settings, for instance:
- Defines default color and layout schemes (for WPF application) (required)
- Defines the shutdown mode (for WPF application) (optional)
- Defines whether only a single instance of the application exists (optional)
- Defines the supported runtime (optional)
- Sartorius defines a corporate design for software, the SAF has integrated corporate design styles of most of the common controls. This section shows how to use the styles out-of-the-box.
The styles are defined in the library Sartorius.SAF.Hid. Within the bootstrapping process of the application the library is searched in the executing directory. If this library is found, the styles and all color definitions are applied to the application.
This means in order to use the corporate styles install the Sartorius.SAF.Hid NuGet package, build the application and start it once again. The style keys used in the HelloWorldView are not recognized until the skin library is found. The most remarkable difference is the background of the view, it changes from white to yellow.
Note
The user can explicitly control whether the skins defined in this library are loaded, by changing the corresponding appSettings key/value pair in the application configuration file of the application, see explanations in SkinManager