Creating a Document

3/30/2010 8:21 PM
You can subscribe to this wiki article using an RSS feed reader.

Assumes you've already created an Add-In.

Create the ViewModel

  1. By convention, create a Documents directory in your Add-In project.
  2. In the Documents directory, create a new class (assume it's called MyDocument for now).  When naming this class, I leave out the ViewModel suffix because in SoapBox Core Add-Ins, everything that isn't a View is a ViewModel.
  3. Visual Studio will put it in the YourNameSpace.YourSubNameSpace.AddInName.Documents namespace, but I suggest removing the .Documents from the end.
  4. Add the following using statements:
    using SoapBox.Core;
    using System.ComponentModel.Composition;

  5. Make your class inherit from AbstractDocument.
  6. Add a constructor, and set the following properties:
    Name = "MyDocument"; // needs to be unique within the entire application
    Title = "Some Title Bar Text"; // Better to use Resources.Strings.MyTitleString to support localization
  7. Create a file called CompositionPoints.cs in the root of your project, if you haven't already.  Here's what it should look like:
    namespace YourNameSpace.YourSubNameSpace.AddInName.CompositionPoints
        public static class Workbench
            public static class Documents
                public const string MyDocument =

  8. Add the following attribute to your class (the first line lets the Workbench tell the Layout manager about it, and makes sure it gets constructed during composition, and the second line is so that other code in your Add-In or other Add-Ins can find your specific document, and show it, etc.):
    [Export(SoapBox.Core.ExtensionPoints.Workbench.Documents, typeof(IDocument))]
    [Export(CompositionPoints.Workbench.Documents.MyDocument, typeof(MyDocument))]
    [Document(Name = "MyDocument")] //
    must match Name property above (hint: use a const)
  9. If you want to execute something when the Document gets focus, then override this method (there is also an OnClosing and OnClosed):
    public override void OnOpened(object sender, System.Windows.EventArgs e)
  10. By default the document is a Singleton (i.e. every document of this type that is shown will just show the same document).  If you want to make your document into a factory (so it has the ability to open multiple documents of the same type), then override the CreateDocument function, and use the memento parameter to determine if you need to return a new instance, or an existing instance that matches the same memento.
  11. Now add any properties that you want the View to bind to. For example:
    public string MyProperty
        get { return "My Property Value"; }

Create the View

We use a WPF DataTemplate to automatically map a View to this ViewModel:

  1. Add a new Resource Dictionary to the Documents project folder, and give it a name of MyDocumentView(.xaml).
  2. Edit the ResourceDictionary tag in the Xaml and add these attributes:
  3. Within the ResourceDictionary contents, add a DataTemplate that maps to your ViewModel:
    <DataTemplate DataType="{x:Type local:MyDocument}">
        <TextBlock Text="{Binding MyProperty}"/>
  4. Add a new code file to the Layout directory and name it MyDocumentView.xaml.cs (has to match the name of the Resource Dictionary but with an additional .cs extension).
  5. Copy and paste this into the new code file (this registers this resource dictionary for insertion into the application resources when the application runs):
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.Composition;
    using System.Windows;

    SoapBox.Core.ExtensionPoints.Host.Views, typeof(ResourceDictionary))]
        public partial class MyDocumentView: ResourceDictionary
            public MyDocumentView()


Showing the Document

From somewhere else in your Add-In (like a menu item, tool bar item, or some other window), you can cause this new document to be shown using the following code:

var newDoc = layoutManager.Value.ShowDocument(myDocument.Value, fileName);

The second parameter is the "memento" string, which should be able to uniquely identify what was open in the document.  You use this string by overriding CreateDocument in your new document class.  This assumes that layoutManager is a reference to a SoapBox.Core ILayoutManager interface and  myDocument is a reference to your new Document.  You generally need to use an Import attribute to get these references, like so:

    [Import(SoapBox.Core.Services.Layout.LayoutManager, typeof(ILayoutManager))]
    private Lazy<ILayoutManager> layoutManager { get; set; }

CompositionPoints.Workbench.Documents.MyDocument, typeof(MyDocument))]
    private Lazy<MyDocument> myDocument { get; set; }

And the class these are in needs to export itself as something that some other Add-In or SoapBox.Core will import during startup.  Typically this is a menu item, tool bar item, or some similar class.

Home: SoapBox Core What's new: Recently changed articles