AvalonDock is a control library targetting WPF which can be used to create user interfaces very similar to VisualStudio.

In the following screenshot you can see SharpDevelop 4 (mirador) running with AvalonDock:

Here are a list of AvalonDock main features:

  1. Almost completely written in C# with .NET 3.5 SP1.
  2. Stylizable appearance with aero and classic themes provided out of the box.
  3. Support for WinForms controls.

AvalonDock is composed of several components that partecipate to the final arrangement of the interface. In this post I will show you how to use AvalonDock in your application. The start point is the root class DockingManager. This class, deriving from ContentControl, must have only one content control which is in the most cases a panel  of type ResizingPanel. DockingManager is responsable to arrange its children (called 'contents') and to perform docking functionalities. In addition you can use it to enumerate, add and remove as well save and restore layout configurations. Looking at above figure DockingManager is the container for all the stuff between the toolbar on the top and the status bar on bottom.

A ResizingPanel is a panel-derived class which arranges its children along a direction (called Orientation as happen in the StackPanel class). Between two consecutive children the ResizingPanel automatically insert a ResizingPanelSplitter. User drag splitters to resize elements of a ResizingPanel (in the same manner of Grid panel).

In AvalonDock 'contents' are objects of type DockableContent or DocumentContent both deriving from ManagedContent. As names suggests a DockableContent is a content which users can redock to a border of the parent DockingManager, can hide or can leave floating over the main window. In the other hand DocumentContents can be only placed internally to the DockingManager, usually in the central area. A typical example of a DockableContent is the 'Properties' window of VS as well as all the tool windows available under 'View' menu item of SharpDevelop. Instead a DocumentContent usually contains a document that user can edit or view. DocumentContents are usually added and removed at runtime, while DockableContents are arranged according to an user preferred layout.

A ManagedContent can be contained in an object of type Pane. A Pane contains a group of contents and defines a SelectedContent property which points to the currently visible content. It works like a TabPanel and derive from Selector. For example in the above figure a Pane is the TabControl containing contents 'Proprietà'(Properties in english) and 'Classi' (Classes). A Pane object is also the container for documents 'MainForm.cs' and 'Program.cs'. There are two kinds of Pane: DocumentPane and DockablePane. A DockablePane can contain only DockableContents and can be dragged and redocked to a border of parent DockingManager. In addition a DockablePane can be autohidden ('unpinned') or floated, that is hosted in a floating window. A DocumentPane can contains both DocumentContents and DockableContents and can't be moved.

To start use AvalonDock, download the latest library binary from CodePlex and install it. Then create a new WPF solution with VisualStudio or SharpDevelop. Open the newly created window named 'Window1.xaml' and select the DockingManager control from toolbox. An other way is to add manually a reference to AvalonDock.dll assembly (which should be placed under %program files%\AvalonDock) and write by your self the following code:

<Window x:Class="AvalonDock.Tutorials.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ad="clr-namespace:AvalonDock;assembly=AvalonDock" 
    Title="Window1" Height="300" Width="300"> 
    <Grid> 
        <ad:DockingManager x:Name="dockManager"> 
        </ad:DockingManager> 
    </Grid> 
</Window> 

DockingManager will occupy all the available space provided by the parent grid. Now the next step is to add a ResizingPanel under the DockingManager. In the following code I added a ResizingPanel with to DockableContent childs.

<ad:DockingManager x:Name="dockManager"> 
    <ad:ResizingPanel> 
        <ad:DockableContent> 
            <TextBox /> 
        </ad:DockableContent> 
        <ad:DockableContent> 
            <TextBox /> 
        </ad:DockableContent> 
    </ad:ResizingPanel> 
</ad:DockingManager>

Build the project and run. You should be able to resize horizontally the two textboxes. Now try to change the orientation of the ResizingPanel setting the dependency property Orientation to Vertical:

<ad:ResizingPanel Orientation="Vertical">

As said a DockablePane can host one or more DockableContent. To see the effect surround the two dockable contents with a DockablePane as show here:

<ad:ResizingPanel Orientation="Vertical"> 
    <ad:DockablePane> 
        <ad:DockableContent Title="TextBox1"> 
            <TextBox /> 
        </ad:DockableContent> 
        <ad:DockableContent Title="TextBox2"> 
            <TextBox /> 
        </ad:DockableContent> 
    </ad:DockablePane> 
</ad:ResizingPanel> 

Run now the project and switch between DockableContents. If you want you can try to change the contents Icon property. DockablePane are represented as a TabControl with tabs bottom aligned but you can change this appereance overloading DockablePane style with your template. I'll show you how to create a different template for DockablePane control in a successive post.

Now its time add Documents to our test. Place a DocumentPane after the DockablePane and revert ResizingPanel Orientation to Horizontal. DocumentPane will containes all the Documents we'll so we need to specify a name for it. Probabily you need to enlarge the window size to see better the DocumentPane:

<ad:DocumentPane x:Name="documentsHost"/>

You can of course change the layout of the window just nesting two or more ResizinPanel. For an example the code below put the second TextBox in a dockable pane anchored to bottom border and add a DocumentPane with a RichTextBox in it just to simulate a multidocument text editor.

<ad:DockingManager x:Name="dockManager"> 
    <ad:ResizingPanel Orientation="Vertical"> 
        <ad:ResizingPanel Orientation="Horizontal" > 
            <ad:DockablePane> 
                <ad:DockableContent Title="TextBox1"> 
                    <TextBox /> 
                </ad:DockableContent> 
            </ad:DockablePane> 
            <ad:DocumentPane x:Name="documentsHost"> 
                <ad:DocumentContent Title="File1.doc"> 
                    <RichTextBox/> 
                </ad:DocumentContent > 
                <ad:DocumentContent Title="File2.doc"> 
                    <RichTextBox/> 
                </ad:DocumentContent > 
            </ad:DocumentPane> 
        </ad:ResizingPanel> 
        <ad:DockablePane> 
            <ad:DockableContent Title="TextBox2"> 
                <TextBox /> 
            </ad:DockableContent> 
        </ad:DockablePane> 
    </ad:ResizingPanel> 
</ad:DockingManager>

Build and run the application you should see something like this:

Try to drag the dockable pane and anchor it to an other border, or try to leave it as floating window. You can arrange DockableContents and DocumentContents as you prefer just like you do in VS or SharpDevelop. In tutorial 2 you will see how to create Documents at runtime, use DockingManager methods and properties as well as check the state of contents. In addition we'll add methods to persist layout configurations using DockingManager.Save/RestoreLayout().

Happy coding!

Download the sample project:

AvalonDock.Tutorials.rar (313.14 kb)

Currently rated 4.2 by 29 people

  • Currently 4.206897/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
59 Comments