Back to Devexpress

MVVM Support - Bind to a Collection of Dock Panels

wpf-11386-controls-and-libraries-layout-management-dock-windows-bind-to-a-collection-of-dock-panels.md

latest14.2 KB
Original Source

MVVM Support - Bind to a Collection of Dock Panels

  • Jan 05, 2024
  • 7 minutes to read

You can use any of the following ways to bind a LayoutGroup / DockLayoutManager to a collection of dock panels.

Populate DockLayoutManager

DockLayoutManager can display dock items which are stored in a ViewModel collection. In this case, DockLayoutManager should contain predefined target layout groups and you should know their names.

Note

Use either the Items or ItemsSource property to specify DockLayoutManager children.

Target Group

Each DockLayoutManager’s dock panel has its target. Target is a layout group where the DockLayoutManager should place dock panels. A target also defines the type of a created dock panel.

Target TypeType of the Created Object
AutoHideGroupLayoutPanel
DocumentGroupDocumentPanel
FloatGroupLayoutPanel
LayoutGroupLayoutPanel
TabbedGroupLayoutPanel

Existing Dock Groups

In this approach, the ViewModel should implement the IMVVMDockingProperties interface. The TargetName property should return the name of the target layout group where DockLayoutManager places the created dock panel.

The following code sample populates DockLayoutManager with the ChildViews ViewModel collection:

csharp
public class MainViewModel : ViewModelBase {
        public ObservableCollection<PanelViewModel> Panels {
            get { return GetValue<ObservableCollection<PanelViewModel>>(); }
            set { SetValue(value); }
        }

        public MainViewModel() {
            Panels = new ObservableCollection<PanelViewModel>() {
                new PanelViewModel() { Caption = "One", Content = "A regular panel", TargetName = "documentGroup" },
                new PanelViewModel() { Caption = "Two", Content = "A regular panel", TargetName = "documentGroup" },
                new PanelViewModel() { Caption = "Three", Content = "A regular panel", TargetName = "documentGroup" },                
                new PanelViewModel() { Caption = "Five", Content = "A panel", TargetName = "layoutGroup" },
            };
        }
    }    

    public class PanelViewModel : ViewModelBase, IMVVMDockingProperties {
        public string Caption {
            get { return GetValue<string>(); }
            set { SetValue(value); }
        }
        public string Content {
            get { return GetValue<string>(); }
            set { SetValue(value); }
        }        
        public string TargetName {
            get { return GetValue<string>(); }
            set { SetValue(value); }
        }
    }
xaml
<UserControl ...
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking">
    <UserControl.DataContext>
        <ViewModels:MainViewModel />
    </UserControl.DataContext>
    <Grid>
        <dxdo:DockLayoutManager ItemsSource="{Binding Panels}">
            <dxdo:DockLayoutManager.Resources>
                <Style x:Key="BaseStyle"
                       TargetType="dxdo:LayoutPanel">
                    <Setter Property="Caption" Value="{Binding Caption}" />
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate>
                                <TextBlock Text="{Binding Content}" />
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
                <Style BasedOn="{StaticResource BaseStyle}" TargetType="dxdo:LayoutPanel" />
                <Style BasedOn="{StaticResource BaseStyle}" TargetType="dxdo:DocumentPanel" />
            </dxdo:DockLayoutManager.Resources>
            <dxdo:LayoutGroup x:Name="root">
                <dxdo:LayoutGroup Name="layoutGroup" />
                <dxdo:DocumentGroup Name="documentGroup" />
            </dxdo:LayoutGroup>
        </dxdo:DockLayoutManager>
    </Grid>
</UserControl>

View Example: Bind the View Model Collection with IMVVMDockingProperties

Non-Existing Dock Groups (Advanced)

You can use the LayoutAdapter to place dock panels to existing dock groups, but also to groups that are not created yet. If you choose the latter option, create the target group before you populate it with panels.

Follow the steps below to use the LayoutAdapter in your application:

  1. Create a LayoutAdapter class that implements the ILayoutAdapter interface.

  2. Implement the Resolve method. The method returns the target layout group name for the specified DockLayoutManager and the panel’s ViewModel. When you implement the Resolve method, you can perform any action before a target name is returned.

  3. Assign a LayoutAdapter instance to the MVVMHelper.LayoutAdapter attached property on the DockLayoutManager to add the LayoutAdapter to DockLayoutManager.

View Example: Bind the View Model Collection with LayoutAdapters

Populate LayoutGroup

This approach allows you to populate a DockLayoutManager.LayoutGroup with a single ViewModel collection.

Note

Use either the Items or ItemsSource property to specify LayoutGroup children.

Dock Panels in Layout Group

Pass the ViewModel collection to the LayoutGroup.ItemsSource property to display dock panels in the LayoutGroup.

xaml
<UserControl ...
    xmlns:dxdo="http://schemas.devexpress.com/winfx/2008/xaml/docking">
    <Window.DataContext>
        <local:MainViewModel />
    </Window.DataContext>
    <Grid>
        <dxdo:DockLayoutManager Name="dockLayoutManager1">
            <dxdo:DockLayoutManager.LayoutRoot>
                <dxdo:LayoutGroup x:Name="root" Caption="LayoutRoot">
                    <dxdo:DocumentGroup x:Name="documentGroup" ItemsSource="{Binding DocumentViews}" />
                    <dxdo:LayoutGroup
                        x:Name="layoutGroup"
                        ItemsSource="{Binding LayoutViews}"
                        Orientation="Vertical" />
                </dxdo:LayoutGroup>
            </dxdo:DockLayoutManager.LayoutRoot>
        </dxdo:DockLayoutManager>
    </Grid>
</UserControl>
csharp
public class MainViewModel : ViewModelBase {
    public ObservableCollection<PanelViewModel> DocumentViews {
        get { return GetValue<ObservableCollection<PanelViewModel>>(); }
        set { SetValue(value); }
    }
    public ObservableCollection<PanelViewModel> LayoutViews {
        get { return GetValue<ObservableCollection<PanelViewModel>>(); }
        set { SetValue(value); }
    }

    public MainViewModel() {
        DocumentViews = new ObservableCollection<PanelViewModel>() { 
            new DocumentViewModel() { Caption = "Document1", Content = "A document panel", Glyph="/Images/change.png" },
            new DocumentViewModel() { Caption = "Document2", Content = "A document panel", Glyph="/Images/create.png" },
            new DocumentViewModel() { Caption = "Document3", Content = "A document panel", Glyph="/Images/new-16x16.png" },
            new DocumentViewModel() { Caption = "Document4", Content = "A document panel" },
        };
        LayoutViews = new ObservableCollection<PanelViewModel>() {
            new PanelViewModel() { Caption = "One", Content = "A regular panel" },
            new PanelViewModel() { Caption = "Two", Content = "A regular panel" },
            new PanelViewModel() { Caption = "Three", Content = "A regular panel" },
            new PanelViewModel() { Caption = "Five", Content = "A regular panel" },
        };
    }
}

public class PanelViewModel : ViewModelBase
{
    public string Caption {
        get { return GetValue<string>(); }
        set { SetValue(value); }
    }
    public string Content {
        get { return GetValue<string>(); }
        set { SetValue(value); }
    }
}
public class DocumentViewModel : PanelViewModel
{
    public string Glyph {
        get { return GetValue<string>(); }
        set { SetValue(value); }
    }
}

View Example: Populate a DockLayoutManager LayoutGroup with the ViewModels collection

Tabbed Panels in Document Group

The TabbedDocumentUIService is an IDocumentManagerService implementation. Use the TabbedDocumentUIService to show documents as tabbed DocumentPanels inside a DockLayoutManager‘s DocumentGroup.

Refer to the following topic for more information: TabbedDocumentUIService.

View Example: Use Services to implement the IDocumentManagerService Interface

Layout Panels in Layout Group

The DockingDocumentUIService is an IDocumentManagerService implementation. Use the DockingDocumentUIService to show documents as a DockLayoutManager‘s LayoutPanels added to a LayoutGroup.

Refer to the following topic for more information: DockingDocumentUIService.

View Example: Use Services to implement the IDocumentManagerService Interface

Configure Generated Panels

Item Template

You can use the following properties to specify how DockLayoutManager renders collection elements:

CollectionCollection Template’s PropertyTemplate Selector
DockLayoutManager.ItemsSourceDockLayoutManager.ItemTemplateDockLayoutManager.ItemTemplateSelector
LayoutGroup.ItemsSourceLayoutGroup.ItemTemplateLayoutGroup.ItemTemplateSelector
xaml
<dxdo:DockLayoutManager.ItemTemplate>
    <DataTemplate>
        <dxdo:LayoutPanel Caption="{Binding DisplayName}" />
    </DataTemplate>
</dxdo:DockLayoutManager.ItemTemplate>

Item Styles

You can create Styles that target the DocumentPanel and LayoutPanel classes to bind the ViewModel fields to dock panels.

xaml
<dxdo:DockLayoutManager.Resources>
    <Style x:Key="BaseStyle" TargetType="dxdo:LayoutPanel">
        <Setter Property="Caption" Value="{Binding Caption}" />
        <Setter Property="ContentTemplate">
            <Setter.Value>
                <DataTemplate>
                    <TextBlock Text="{Binding Content}" />
                </DataTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    <Style BasedOn="{StaticResource BaseStyle}" TargetType="dxdo:LayoutPanel" />
    <Style BasedOn="{StaticResource BaseStyle}" TargetType="dxdo:DocumentPanel" />
</dxdo:DockLayoutManager.Resources>

View Example: Bind the View Model Collection with IMVVMDockingProperties

Data Templates

You can define DataTemplates that target the dock panel ViewModel to initialize panel contents.

xaml
<Application.Resources>
    <DataTemplate DataType="{x:Type local:PanelViewModel}">
        <Grid>
            <Button Content="{Binding Glyph}"/>
        </Grid>
    </DataTemplate>
</Application.Resources>

See Also

DockingDocumentUIService

TabbedDocumentUIService

Save and Restore the Layout of Dock Panels and Controls