MVVM Features
The Docking & MDI product has been designed to support the popular MVVM pattern. The DockSite control's item container generation features and infrastructure are similar to a standard ItemsControl
, but geared towards the generation of docking windows.
Tip
Many of the concepts below are implemented in the MVVM-related samples in the Sample Browser, so be sure to examine those samples.
Specifying Document and Tool Items
The DockSite includes several properties and methods that mimic the design of the native ItemsControl
. Using these properties and methods, the DockSite can be bound to a collection of view-models for documents and/or tool windows.
Document Windows
Document windows can be defined by binding the DockSite.DocumentItemsSource property to a collection of items, such as view-models. The items will be wrapped in an instance of DocumentWindow, which is the container used to present the item.
A Style
can be applied to the generated DocumentWindow instances by using the DockSite.DocumentItemContainerStyle or DocumentItemContainerStyleSelector properties. Alternatively, an implicit Style
for the DocumentWindow type can be defined and placed in the Application.Resources
. The Style
can be used to bind various properties of the DocumentWindow to the item.
The DataTemplate
used by the DocumentWindow instances to present the associated item can be specified using the DockSite.DocumentItemTemplate or DocumentItemTemplateSelector properties. Alternatively, an implicit DataTemplate
for the item's type can be defined and placed in the Application.Resources
.
Tool Windows
Tool windows can be defined by binding the DockSite.ToolItemsSource property to a collection of items, such as view-models. The items will be wrapped in an instance of ToolWindow, which is the container used to present the item.
A Style
can be applied to the generated ToolWindow instances by using the DockSite.ToolItemContainerStyle or ToolItemContainerStyleSelector properties. Alternatively, an implicit Style
for the ToolWindow type can be defined and placed in the Application.Resources
. The Style
can be used to bind various properties of the ToolWindow to the item.
The DataTemplate
used by the ToolWindow instances to present the associated item can be specified using the DockSite.ToolItemTemplate or ToolItemTemplateSelector properties. Alternatively, an implicit DataTemplate
for the item's type can be defined and placed in the Application.Resources
.
Container Customization
The DockSite includes several virtual methods that can be overridden to customize the containers created based on the bound items. These methods mimic the native ItemsControl
and includes ClearContainerForItemOverride, GetContainerForItemOverride, IsItemItsOwnContainerOverride, and PrepareContainerForItemOverride. Each of these methods works like its ItemsControl
counterpart, with one exception. Each method includes an additional parameter that specifies whether the container is for a document or tool item.
The PrepareContainerForItemOverride method override could be used to bind your view model's properties to the containing docking window's related properties. The ClearContainerForItemOverride method override would clear those bindings. You don't need to override these methods if you are setting up your bindings in a Style
instead that gets used by DocumentItemContainerStyle, ToolItemContainerStyle, etc.
Content and Template
As with a standard ItemsControl
bound to a collection of view model items, each item will be assigned to the Content
property of the generated container docking window.
These view model items require that a content template be specified to properly render their data. As mentioned above, the DocumentItemTemplate, DocumentItemTemplateSelector, ToolItemTemplate, and ToolItemTemplateSelector properties can be used to designate the DataTemplate
to use for each item.
Styling the Document and Tool Windows
Custom styles can easily be applied to the DocumentWindow and/or ToolWindow containers created for the bound items. The DocumentItemContainerStyle, DocumentItemContainerStyleSelector, ToolItemContainerStyle, or ToolItemContainerStyleSelector properties can be used to apply a custom Style
. Alternatively, an implicit Style
for the DocumentWindow and/or ToolWindow types can be defined. The Style
can be used to bind various properties of the DocumentWindow and/or ToolWindow to the item.
These styles pulled from our MVVM samples in the Sample Browser show how you can bind various view model properties to the docking windows. The resulting DocumentWindowStyle
and ToolWindowStyle
properties could then be set to the DockSite.DocumentItemContainerStyle and ToolItemContainerStyle properties respectively:
xmlns:common="clr-namespace:ActiproSoftware.ProductSamples.DockingSamples.Common"
xmlns:docking="http://schemas.actiprosoftware.com/winfx/xaml/docking"
...
<common:ToolItemDockSideConverter x:Key="ToolItemDockSideConverter" />
<common:ToolItemStateConverter x:Key="ToolItemStateConverter" />
<Style x:Key="DockingWindowStyle" TargetType="docking:DockingWindow">
<Setter Property="Description" Value="{Binding Path=Description, Mode=TwoWay}" />
<Setter Property="ImageSource" Value="{Binding Path=ImageSource, Mode=TwoWay}" />
<Setter Property="IsActive" Value="{Binding Path=IsActive, Mode=TwoWay}" />
<Setter Property="IsOpen" Value="{Binding Path=IsOpen, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
<Setter Property="SerializationId" Value="{Binding Path=SerializationId, Mode=TwoWay}" />
<Setter Property="Title" Value="{Binding Path=Title, Mode=TwoWay}" />
<Setter Property="WindowGroupName" Value="{Binding Path=WindowGroupName, Mode=TwoWay}" />
</Style>
<Style x:Key="DocumentWindowStyle" TargetType="docking:DocumentWindow" BasedOn="{StaticResource DockingWindowStyle}">
<Setter Property="FileName" Value="{Binding Path=FileName, Mode=TwoWay}" />
<Setter Property="IsReadOnly" Value="{Binding Path=IsReadOnly, Mode=TwoWay}" />
</Style>
<Style x:Key="ToolWindowStyle" TargetType="docking:ToolWindow" BasedOn="{StaticResource DockingWindowStyle}">
<Setter Property="DefaultDockSide" Value="{Binding Path=DefaultDockSide, Mode=TwoWay, Converter={StaticResource ToolItemDockSideConverter}}" />
<Setter Property="State" Value="{Binding Path=State, Mode=TwoWay, Converter={StaticResource ToolItemStateConverter}}" />
</Style>
Layout Serialization Support
If you plan on serializing your layout between application execution sessions, you must assign your docking windows a unique Name
or SerializationId. It is recommended that you use the SerializationId property since unlike the Name
property, it can be bound easier and allows any character to be used in the value.
Opening and Positioning the Docking Windows
The DocumentWindow and/or ToolWindow containers created for the bound items will initially be closed and must be opened to appear in the visible layout.
Numerous bindable properties are available on DockingWindow for determining the state and position of docking windows, along with whether they are open and active. For instance, the State property can be set to designate which state the window should open in. This property must remain Document
for any DocumentWindow. To open a docking window and add it to the layout, set its IsOpen property to true
. To open a docking window (if it isn't already open) and ensure its selected and focused, set its IsActive property to true
. This can be done instead of setting IsOpen. Finally, to make sure an already-open docking window's tab is selected, set its IsSelected property to true
.
When a docking window is opened via its IsOpen or IsActive properties, it will open in a default location. There are numerous properties and events available that allow you to customize this default location prior to opening the docking window. Some examples are ToolWindow.DefaultDockSide, DockingWindow.WindowGroupName, DockSite.WindowDefaultLocationRequested, etc.
If you prefer to open, activate, dock, etc. a docking window in code-behind instead, this can be easily accomplished by adding a handler for the DockSite.WindowRegistered event. This event is fired once per DocumentWindow and/or ToolWindow when it is initially registered with the DockSite.
The following code shows an example of a WindowRegistered
handler:
dockSite.WindowRegistered += this.OnDockSiteWindowRegistered;
// ...
/// <summary>
/// Handles the <c>WindowRegistered</c> event of the <c>DockSite</c> control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="DockingWindowEventArgs"/> instance containing the event data.</param>
private void OnDockSiteWindowRegistered(object sender, DockingWindowEventArgs e) {
DockSite dockSite = sender as DockSite;
if (dockSite == null)
return;
// Ensure the DockingWindow exists and is generated for an item
DockingWindow dockingWindow = e.Window;
if (dockingWindow == null || !dockingWindow.IsContainerForItem)
return;
// Open the DockingWindow, if it's not already open
if (!dockingWindow.IsOpen) {
// ** Open window in desired location here
}
}
Item Containers
The DockingWindow.IsContainerForItem property returns true
when a docking window is a generated container for an item in the DockSite.DocumentItemsSource or DockSite.ToolItemsSource collections.
The ContainerFromItem method can be used to retrieve the DocumentWindow or ToolWindow associated with a given item. If the type of the item is known, then the ContainerFromDocumentItem or ContainerFromToolItem methods can be used instead.
Item Container Unregistration Triggering Items Source Update
The DockSite.CanUpdateItemsSourceOnUnregister property indicates whether to watch the WindowUnregistered event for an item container DockingWindow to be unregistered. If that property is true
, the dock site will try to automatically remove the related item from the appropriate DockSite.DocumentItemsSource or DockSite.ToolItemsSource collection.
The functionality will only succeed if the ItemsSource
is an IList
that is not read-only or fixed size.
In scenarios where the above conditions are not met, it is up to you to watch the WindowUnregistered event and remove the related item from its items source.
Troubleshooting
See the Troubleshooting topic for more information, with some specific details on configuring data contexts properly.