A Simple Example for the SoapBox Framework (WPF, .NET)

SoapBox Core uses WPF's MEF to provide a base application framework that is easy to extend. This is a simple example that includes elements of a basic application (toolbar, statusbar, document area, etc.).

Introduction

The demo project that is introduced with the SoapBox framework is a pinball game. It demonstrates a few things that the framework provides, but is missing a few that
are integral to many applications. A toolbar, for example.

I did not find the pinball example particularly useful for my own use and started writing code to figure
out how various parts of SBC work in a simple example of my own. I figured I would share my results here.

Also, as it's written, the SoapBox framework is a set of projects within solution folders, and SoapBox.Core.Host is output as an executable. So using SoapBox requires that we include the whole set of SoapBox projects within our local solution and set SBC Host as the startup project. There are several problems with this:

Including these extra projects is kind of messy (and can increase compile time).

When SoapBox has an update, updating the SoapBox projects in all of our projects is messy.

The Express editions of Visual Studio don't support solution folders (they also don't support mixed languages, so can't use the SoapBox C# sources within, say, a Visual Basic project). (As a workaround, you can use SharpDevelop or MonoDevelop (buggy?) to open projects that use solution folders or mixed languages.)

Overview

So for this article, first I will describe how to set up the SoapBox.Core.Host so the SBC can be used as a set of DLLs. The example project also moves the DLLs into separate folders instead of having them all in the application's base folder.

Second, I will present a simple example solution containing a startup project and a "feature" project that has some basic things most applications need (toolbar, status bar, document area, etc.).

Modifying SoapBox.Core.Host

First, change the project type from WinExe to Library.

Second, rename App.xaml.cs to App.cs and remove App.xaml.
The attached source code has the details for the new file. It is mainly a copy of App.xaml.cs, plus some things I added for setting and accessing its catalog.

You may also need to manually remove this line from SoapBox.Core.Host.csproj:

<StartupObject>SoapBox.Core.Host.App</StartupObject>

Now you can build the SoapBox solution and then copy whichever DLLs you want to use to your own project library.

Creating the Startup Project (Example.Host)

This project outputs the executable file that starts the application. Pretty much all it does is provide references to the SBC DLLs and then set up and run the framework. Then the framework does the rest of the work. Here's a step-by-step.

In Windows Explorer (not Visual Studio), create a folder (named Lib) in the solution folder and put all of the SoapBox, NLog, and AvalonDock DLLs in it.

Add references to all of the DLLs in the Lib folder. We need references to all of these with the Visual Studio "Copy Local" property set to true, even though Example.Host doesn't explicitly need some of them, so they get copied to the output folder. (This is one way to do it; there's a number of different ways to get these copied to the output folders.)

Add a reference to System.ComponentModel.Composition

Delete
App.xaml, MainWindow.xaml, and related .cs files.

Add
Program.cs with a Main that creates a new SoapBox.Core.Host.App() object.

Add catalogs to the app object, so SBC knows where to look for them.

Add a call to Run() on the app object.

Change the build Location to ..\bin\Debug and ..\bin\Release (Be *sure* that all projects output to the correct folders or you will be scratching your head when things don't appear in the application when you run it).

At this point, if you run the project, you should get a plain workbench (bigger than the screenshot, but otherwise the same).

Creating an Example "Feature" Project (Example.HelloWorld)

For each main "feature" of your application, you'll want a separate project. For a more loosely coupled solution, all features would refer to common project, such as the "Contracts" project that appears in SoapBox examples. For simplicity (and because there's only one feature), all of the contracts are in HelloWorld (see the CompositionPoints and ExtensionPoints files in the source code).

You might also want to set up one of the features (or even the 'host" project above) as the main shell, to provide a "main" toolbar, about box, etc.

The example application demonstrates the following items:

Application icon. SoapBox examples use a way that the author comments as "hacky", which creates a Window class and sets the icon with the VS designer... I implemented a "less hacky" one- or two-liner method that reads the image as an embedded resource. Namely,

// Set application icon by reading it as an embedded resource
Uri u = new Uri("pack://application:,,,/Example.HelloWorld;component/App/star.png", UriKind.Absolute);
mainWindow.Value.Icon = new BitmapImage(u);

SBC StartupCommands (Shutdown commands are similar). The startup command in this example is used to display the recipe document and instructions pad when the application starts.

An SBC Pad (the pinball demo uses a pad, as well).

An SBC Document. SBC Document and Pad XAMLs are based on ResourceDictionaries with a DataTemplate, which are not editable in Visual Studio designer. This example demonstrates referencing a UserControl so that the Visual Studio designer CAN be used to edit the layout. Not a big advantage for a simple example like this, but great if the layout is more complex.

An SBC ToolBar with a ToolBarButton that is linked via an
IExecutableCommand to perform some action (display a MessageBox).

An SBC StatusBar with several different items in it.

Adding items to the menu (such as the About item).

Here is the most basic step-by-step, as a recipe for creating one of these projects.

Add a New WPF project, named Example.HelloWorld, to the solution. I find this easier than using a library project and then having to add all of the WPF references.

Delete
App.xaml, MainWindow.xaml, and associated .cs files.

In the project properties, change the project type to Class Library.

Add a reference to System.ComponentModel.Composition

Add a reference to Soapbox.Core.Contracts

Change the build Location to ..\bin\Debug

Start adding SBC items by using Export and Import as needed....

Points of Interest

I messed around for a while trying to figure out how to merge the SBC DLLs into a single file. ILMerge, the traditional method, doesn't work for WPF. Several other methods I tried didn't work and gave me various errors that I think meant MEF couldn't find the correct assemblies or that the same assembly was being loaded in different contexts.

I came across your project and trying to get it working but unfortunately no luck yet.
I have the original SBC code with the pinball example working, but when I downloaded your example project, I am unable to have it running out of the box. Tried the attached files you provided and also tried to get the new example going as you described.
I am missing a mot likely minor detail to have your project work with the Host for SBC.

Is there a project which works out of box? I am using the Visual Studio Express 2013.

In the "Modifying SoapBox.Core.Host" section you say "Now you can build the SoapBox solution ". What solution? Do I make a new solution ? What do I include in it? All of the SoapBox.Core projects? Only the SoapBox.Core.Host project? That doesn't simply compile. What are the dependencies on this? I could get as far missing "Composition" in order to build SoapBox.Core.Contracts.

I downloaded your modified source, and I experienced the same issues and questions. In that solution you only have SoapBox.Core.Host, and equally it doesn't compile off the bat, missing refferences to "IArgumentsService" and a lot of other ones.

http://soapboxautomation.com/products/soapbox-core-2/download/[^]
If you download the SoapBox.Demo solution from the above link, you'll get a whole bunch of projects. I actually downloaded mine using Subversion. All dependencies are included in the download. The SoapBox.Core.Host project (which you should be able to replace with my modified one) is in the path '/SoapBox/SoapBox.Core/SoapBox.Core.Host'.

If you just use my modified project, you'll need to satisfy some references. You'll need SoapBox.Core.Contracts, NLog, and (possibly?) AvalonDock. You'll need the same versions of these as the other SoapBox.Core DLLs or you'll get errors about conflicts.