WPF Application - kaisu1986/ATF GitHub Wiki
WinForms and WPF applications use ATF in similar ways. This section discusses their differences in basic application structure. The other sections in ATF Application Basics and Services also mention similarities and differences between WinForms and WPF.
For an example of a WPF ATF application, see the ATF Wpf App Sample. For a WinForms application that shares code with this WPF sample and helps clarify the similarities and differences between the two, see the ATF Win Forms App Sample.
App.xaml
is the XAML file in which the WPF application is set up:
<atf:AtfApp x:Class="WpfApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:atf="http://www.sce.net/Atf.Gui.Wpf">
</atf:AtfApp>
This partially defines the class WpfApp.App
, which is derived from the ATF class AtfApp
. The rest of the WpfApp.App
class definition is in the C# file App.xaml.cs
, which sets up the MEF catalog, as discussed in MEF Setup.
The AtfApp
class is the base ATF WPF application class and derives from System.Windows.Application
. You should derive WPF applications from this class to avoid rewriting common code. AtfApp
implements IComposer
, which is an interface for ComposablePart
and CompositionContainer
used for WPF applications with MEF.
AtfApp
's constructor performs some of the same set up functions as the WinForms Main()
function discussed in Initial Setup:
public AtfApp()
{
// Setup thread name and culture
Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentCulture;
Thread.CurrentThread.Name = "Main";
// Ensure the current culture passed into bindings is the OS culture.
// By default, WPF uses en-US as the culture, regardless of the system settings.
FrameworkElement.LanguageProperty.OverrideMetadata(
typeof(FrameworkElement), new FrameworkPropertyMetadata(
XmlLanguage.GetLanguage(System.Globalization.CultureInfo.CurrentCulture.IetfLanguageTag)));
}
Much of AtfApp
is dedicated to composing components with MEF, which is discussed next in MEF Setup.
If a WPF application uses MEF, it needs to specify the components it uses. This section discusses a way to do this using AtfApp
.
AtfApp
has an OnStartup()
method that is called when a WPF application starts up:
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (Compose())
{
OnCompositionBeginning();
foreach (var initializable in m_initializables)
initializable.Value.Initialize();
OnCompositionComplete();
m_mainWindow.ShowMainWindow();
}
else
{
Shutdown();
}
}
OnStartup()
calls the Compose()
method to compose the MEF components. In turn, Compose()
calls the abstract method GetCatalog()
, which actually sets up the MEF catalog. OnStartup()
also initializes all the MEF components using the ATF IInitializable.Initialize()
method.
The ATF application should provide a GetCatalog()
implementation that sets up the MEF catalog. Here's how the ATF Wpf App Sample does it in App.xaml.cs
, defined in the partial class App
:
public partial class App : AtfApp
{
protected override AggregateCatalog GetCatalog()
{
var typeCatalog = new TypeCatalog(
typeof(SettingsService), // persistent settings and user preferences dialog
typeof(CommandService), // handles commands in menus and toolbars
typeof(ControlHostService), // docking control host
typeof(AtfUsageLogger), // logs computer info to an ATF server
typeof(CrashLogger), // logs unhandled exceptions to an ATF server
typeof(UnhandledExceptionService), // catches unhandled exceptions, displays info, and gives user a chance to save
typeof(ContextRegistry), // central context registry with change notification
typeof(StandardFileExitCommand), // standard File exit menu command
typeof(FileDialogService), // standard Windows file dialogs
typeof(DocumentRegistry), // central document registry with change notification
typeof(StandardFileCommands), // standard File menu commands for New, Open, Save, SaveAs, Close
typeof(AutoDocumentService), // opens documents from last session, or creates a new document, on startup
typeof(RecentDocumentCommands), // standard recent document commands in File menu
typeof(MainWindowTitleService), // tracks document changes and updates main form title
typeof(WindowLayoutService), // service to allow multiple window layouts
typeof(WindowLayoutServiceCommands), // command layer to allow easy switching between and managing of window layouts
typeof(SchemaLoader), // loads schema and extends types
typeof(MainWindow), // main app window (analog to 'MainForm' in WinFormsApp)
typeof(Editor), // Sample editor class that creates and saves application documents
typeof(PythonService), // scripting service for automated tests
typeof(ScriptConsole), // provides a dockable command console for entering Python commands
typeof(AtfScriptVariables), // exposes common ATF services as script variables
typeof(AutomationService) // provides facilities to run an automated script using the .NET remoting service
);
return new AggregateCatalog(typeCatalog, StandardInteropParts.Catalog, StandardViewModels.Catalog);
}
}
The GetCatalog()
method returns an AggregateCatalog
, which contains the TypeCatalog
with the components the sample application uses — as well as a couple of ComposablePartCatalog
objects containing WPF versions of ATF components that are generally useful for WPF applications: StandardInteropParts.Catalog
and StandardViewModels.Catalog
. For more information on StandardInteropParts
, see Using WinForms Controls in WPF.
AtfApp
also provides a OnExit()
called when the WPF application exits. OnExit()
disposes of MEF components' resources. You can override it to perform additional clean up. Here is the base method:
protected override void OnExit(ExitEventArgs e)
{
base.OnExit(e);
foreach (var disposable in m_disposables)
{
disposable.Value.Dispose();
}
if (Container != null)
{
Container.Dispose();
}
}