Discovering open source WPF components – Orc.WorkspaceManagement

In the discovering open source WPF components series, I will look into useful open source components that can be used to create WPF apps. This weeks component is Orc.WorkspaceManagement.

Workspaces are a great way to empower your end-users to customize the layout of the screen to their own good. There are a lot of different components that can be customized inside an application (some views need settings to be stored, others should be ignored, etc). Orc.WorkspaceManagement provides a nice wrapper around this so whenever the user wants to store a workspace, each component can be stored separately using providers.


Retrieving a list of workspaces

Retrieving the current workspace

Retrieving the currently selected workspace is very easy:

To get a typed instance:

Implementing providers

Providers are classes that do the hard work. They will take care of actually saving and loading the state of a specific workspace. Below is a provider that will store the IsMinimized state of a ribbon:

Storing and saving workspaces

The last step is storing workspaces and saving workspaces to disk. Since all the hard work is done by the IWorkspaceManager, it’s very easy to implement this final step.

Storing the workspace means the workspace manager will call all providers to gather their data so the UI state as it’s currently visible on the screen will be persisted into the current active workspace:

To save all workspaces in the workspace manager to disk, use the following code:

Workspace management in C#

Recently I was working on a few projects that required the management of workspaces. Workspaces is a fancy term for a document, a list of documents or anything in between. I noticed that I was implementing the same logic over and over again so decided to create a library (and NuGet package) from the experiences.

The Orc.WorkspaceManagement package is currently in prerelease but I use it in several products.

The workspace management library makes it easy to manage workspaces. The main component is the IWorkspaceManager that contains the current workspace and allows to load or save a workspace. Note that this library does not force you to use a specific workspace location of any sort, so it can even be a database or server call to read / write the workspace.

Below is an overview of the most important components:

  • IWorkspace => the actual workspace object
  • IWorkspaceManager => the workspace manager with events and management methods
  • IWorkspaceInitializer => allows customization of initial settings of a workspace
  • IWorkspaceReader => reads a workspace from a location
  • IWorkspaceWriter => writes a workspace to a location

Creating a workspace

A workspace is a model that can be implemented by the developer and must implement the IWorkspace interface. The most convenient way to implement a workspace is by deriving from the WorkspaceBase class:

Creating a workspace initializer

When a workspace manager is created, it doesn’t contain anything. The IWorkspaceInitializer interface allows the customization of that state.

By default the following initializers are available:

  • EmptyWorkspaceInitializer => initializes nothing, this is the default
  • DirectoryWorkspaceInitializer => First checks if there is an app config setting called DataLocation. If so, it will use that. If not, it will fall back to %AppData%\[assembly company]\[assembly product]\data. Then it will also check if a command line directory is passed (first argument). If so, all previous will be overriden by the command line directory.

To create a custom workspace initializer, see the example below:

Next it can be registered in the ServiceLocator (so it will automatically be injected into the WorkspaceManager):

Make sure to register the service before instantiating the IWorkspaceManager because it will be injected

Creating a workspace reader service

Workspaces must be read via the IWorkspaceReaderService. The workspace manager automatically knows when to read a workspace. First, one must create a workspace reader as shown in the example below:

Next it can be registered in the ServiceLocator (so it will automatically be injected into the WorkspaceManager):

Creating a workspace writer service

Next it can be registered in the ServiceLocator (so it will automatically be injected into the WorkspaceManager):

Retrieving a type instance of the workspace

The library contains extension methods for the IWorkspaceManager to retrieve a typed instance: