This is a program proposal for a standard MVVM application architecture that you can use with small adjustments for your Windows desktop applications.
Introduction
I recently asked myself why I have to make a preliminary decision when creating a project in Visual Studio about what type of user interface I would like to use later. Isn't it often claimed that a user interface must be interchangeable without affecting the other layers? So I started to look at what makes WinForms and WPF applications different and what they might have in common. I have re-analyzed my own old template application that I used myself for years, rebuilt it, and reduced it to the essentials.
The result of my attempts is a standard MVVM application that can be used unchanged for different types of user interfaces.
BasicApplication Demo
For this demo, the name of the user interface to be ultimately used can be transmitted via the command line. Two types of user interfaces have been implemented so far: WinForms and WPF. Also, the IsSingleInstance
parameter can be used to specify whether this application can be started multiple times or not. This parameter can also be transferred via the command line.
Since the correct exception handling involves some difficulties (especially with WPF user interfaces), this demo is delivered with complete exception handling. The application itself is predefined as a Windows-application in the Visual Studio project settings, but it also works as a console-application. For tests of exception handling, various test exceptions were commented out and saved in the code. If you want to test exception handling, I recommend running the application without debugging (use Ctrl-F5) and as a console application (to see additional test output).
Using the Code
Download the source, extract it and open the solution in Visual Studio.
To debug, set BasicAplication
as Startup project.
Here, you can see on the left a sequence of test-messages during a normal run and the project structure in Visual Studio to the right:
The Run- and Stop-Buttons have no function. They are only for demonstrating button-handling.
Basic Principles
The "BasicApplication
" start project with the "Program
" and "AppStarter
" classes can be used almost unchanged for other applications. Exceptions are the test displays, test exceptions, and possibly your own initializations and disposals, see the following code excerpt from BasicApplication.AppStarter
:
private void PrepareStart()
{
}
private void Cleanup()
{
if (this._app != null)
{
this._app.UIShutdown -= OnUIShutdown;
this._app.UIStartup -= OnUIStartup;
}
try
{
this._businessLogicViewModel?.Dispose();
}
catch { }
try
{
this._businessLogic?.Dispose();
}
catch { }
Program.Say("Clean up done.");
}
Other points of interest are documented in the code so that there should be no need for further code snippets.
The Model
and ViewModel
projects and their classes only need to be adapted concerning business-specific requirements. The basic structure and all interface classes can also remain unchanged.
The project "DependencyInjection
" as well as the class "Model.AppSettings
" are just made for this demo. They help to make the demo work with command-line parameters and UI-injection.
If you plan to use the code in a production environment, you should remove the test-displays, test-exceptions, and console output, have your own "AppSettings
", and finally decide, which UI to use so that dependency injection is no longer required.
Conclusion and Points of Interest
I know this article is more of an architecture discussion than a much-needed application. If you find this article helpful or if you have criticism or suggestions for improvement, I would be very happy to hear from you. Of course, it would be particularly interesting to see whether other UI types could be implemented or what the whole thing would look like on other project platforms.
History
- 16th November, 2020: Initial version