I need to load a collection of items as documents in AvalonDock 2.0. These objects inherit from an abstract class, for which I want to render a frame inside the document depending on which subclass are.
This is my XAML:
<ad:DockingManager Background="Gray" DocumentsSource="{Binding Path=OpenProjects}" 
        ActiveContent="{Binding Path=CurrentProject, Mode=TwoWay}">
    <ad:DockingManager.DocumentHeaderTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=OpenProjects/Name}" />
        </DataTemplate>
    </ad:DockingManager.DocumentHeaderTemplate>
    <ad:DockingManager.LayoutItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.Resources>
                    <DataTemplate DataType="{x:Type vm:SubclassAViewModel}">
                        <Frame Source="Pages/SubclassAProject.xaml" />
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vm:SubclassBViewModel}">
                        <Frame Source="Pages/SubclassBProject.xaml" />
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type vm:SubclassCViewModel}">
                        <Frame Source="Pages/SubclassCProject.xaml" />
                    </DataTemplate>
                </Grid.Resources>
            </Grid>
        </DataTemplate>
    </ad:DockingManager.LayoutItemTemplate>
    <ad:LayoutRoot>
        <ad:LayoutPanel>
            <ad:LayoutDocumentPaneGroup>
                <ad:LayoutDocumentPane>
                </ad:LayoutDocumentPane>
            </ad:LayoutDocumentPaneGroup>
        </ad:LayoutPanel>
    </ad:LayoutRoot>
</ad:DockingManager>
So far I've achieved to show as many documents as items are in the OpenProjects collection, but I can't seem to show anything inside each document. 
Plus, I don't know if I'm using ActiveContent properly: I want to assign to CurrentProject the ViewModel assigned on the current active document.
Thank you for your time.
                        
The reason why you are not able to see any content is of the way you defined your
LayoutItemtemplates. This can't work.Also consider to use a custom control instead of the
Frame. TheFrameis very heavy. Unless you don't need to display HTML, avoid this control. Content navigation is very easy to implement, in case you want to show navigable content. Just wrap your document content into aUserControl.You are using the
ActiveContentproperty properly.To fix your problem you have three recommended solutions, where the first doesn't exactly meet your requirements. Since you defined the
DockingManager.LayoutItemTemplatewrong, I will show it anyway.Solution 1: Local
LayoutItemTemplateIn case you only need a single template for all
LayoutDocumentandLayoutAnchorablecontainers, you can use theDockingManager.LayoutItemTemplateproperty. This property accepts a singleDataTemplate. NestedDataTemplatedefinitions, like in your code, are generally not supported by WPF.Solution 2: Implicit
DataTemplateIn more advanced scenarios you display different views based on different models. If the displayed content depends on the data type of the model alone (like in your case), the recommended approach is to provide implicit
DataTemplatedefinitions.WPF will automatically apply an implicit
DataTemplateto every data type that matches theDataTemplate.TargetTypeof this template.The
DataTemplateis implicit, if it has no explicitx:Keyvalue assigned. To ensure that theDataTemplatecan actually be applied automatically, theDataTemplatemust also be defined in the same resource scope as the target type. E.g., defining theDataTemplateinApplication.Resourcesof App.xaml, would make the template to be applied automatically in the application scope.Solution 3:
DataTemplateSelectorThe previous solution, which uses implicit
DataTemplatedefinitions, can be replaced with aDataTemplateSelector.DataTemplateSelectoris another WPF concept to apply aDataTemplateselectively.A
DataTemplateSelectoris the recommended choice, if selecting aDataTemplatemay depend on more complex constraints, than the model's data type alone. It allows to e.g. evaluate the data item and chose the appropriate template based on certain criteria.To define a template selector, you have to extend
DataTemplateSelector, which is expected to return aDataTemplate.The easiest way is to define the templates in App.xaml resource dictionary using an
x:Keyand then select from them based on the condition.DockingMangeraccepts a template selector by assigning theDockingManager.LayoutItemTemplateSelectorproperty:App.xaml
Define the explicit
DataTemplateusingx:Key:DocumentManagerTemplateSelector.cs
The following code uses the Switch Expression, which is available since C# 8.0. It can be replaced with a switch statement or cascaded if-statements.
MainWindow.xaml