How to implement SDI using MVVM?

Mar 22, 2012 at 3:41 PM

Hi guys,

Wanted to ask if someone knows how to create a Single document interface using MVVM pattern and AvalonDock. I need to create an interface which will contain some auto-hiding tool windows and main window (which will draw the scene, called Viewport). Now I have something like this:

 <ad:DockingManager Grid.Row="2" x:Name="m_DockingManager" DocumentsSource="{Binding Viewports}" AnchorablesSource="{Binding ToolWindows}">
            <!--describes views for documents group-->
            <ad:DockingManager.DocumentTemplateSelector>
                <viewmodels:ViewModelsTemplateSelector>
                    <viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                        <DataTemplate>
                            <views:Viewport/>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                    <viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                        <DataTemplate>
                            <views:Browser/>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                    <viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                        <DataTemplate>
                            <views:Properties/>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                </viewmodels:ViewModelsTemplateSelector>
            </ad:DockingManager.DocumentTemplateSelector>
            <!--describes panels or documents headers for documents group-->
            <ad:DockingManager.DocumentHeaderTemplateSelector>
                <viewmodels:ViewModelsTemplateSelector>
                    <viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                        <DataTemplate>
                            <Border>
                                <TextBlock Text="{Binding Path=Content.Name}"/>
                            </Border>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                    <viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                        <DataTemplate>
                            <Border>
                                <TextBlock Text="{Binding Path=Content.Name}"/>
                            </Border>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                    <viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                        <DataTemplate>
                            <Border>
                                <TextBlock Text="{Binding Path=Content.Name}"/>
                            </Border>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                </viewmodels:ViewModelsTemplateSelector>
            </ad:DockingManager.DocumentHeaderTemplateSelector>
            <!--describes document header when floating-->
            <ad:DockingManager.DocumentTitleTemplateSelector>
                <viewmodels:ViewModelsTemplateSelector>
                    <viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                        <DataTemplate>
                            <Border>
                                <TextBlock Text="{Binding Path=Content.Name}"/>
                            </Border>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.ViewportViewModelTemplate>
                </viewmodels:ViewModelsTemplateSelector>
            </ad:DockingManager.DocumentTitleTemplateSelector>
            <ad:DockingManager.DocumentTitleTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Path=Content.Name}"/>
                    </Border>
                </DataTemplate>
            </ad:DockingManager.DocumentTitleTemplate>
            <ad:DockingManager.DocumentHeaderTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Path=Content.Name}"/>
                    </Border>
                </DataTemplate>
            </ad:DockingManager.DocumentHeaderTemplate>

            <!--describes views for panel-->
            <ad:DockingManager.AnchorableTemplateSelector>
                <viewmodels:ViewModelsTemplateSelector>
                    <viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                        <DataTemplate>
                            <views:Browser/>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.BrowserViewModelTemplate>
                    <viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                        <DataTemplate>
                            <views:Properties/>
                        </DataTemplate>
                    </viewmodels:ViewModelsTemplateSelector.PropertiesViewModelTemplate>
                </viewmodels:ViewModelsTemplateSelector>
            </ad:DockingManager.AnchorableTemplateSelector>

            <!--describes panels headers for pane group-->
            <ad:DockingManager.AnchorableHeaderTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Path=Content.Name}"/>
                    </Border>
                </DataTemplate>
            </ad:DockingManager.AnchorableHeaderTemplate>
            <!--describes header for panel when floating-->
            <ad:DockingManager.AnchorableTitleTemplate>
                <DataTemplate>
                    <Border>
                        <TextBlock Text="{Binding Path=Content.Name}"/>
                    </Border>
                </DataTemplate>
            </ad:DockingManager.AnchorableTitleTemplate>            
            
            <ad_layout:LayoutRoot>
                <ad_layout:LayoutPanel Orientation="Horizontal">
                    <ad_layout:LayoutDocumentPane/>
                    <ad_layout:LayoutAnchorablePane DockWidth="250"/>
                </ad_layout:LayoutPanel>
            </ad_layout:LayoutRoot>        
        </ad:DockingManager>

But in this case I can have multiply Viewports, need only one which can not be closed but with header on the above

Mar 22, 2012 at 6:28 PM

Peace,

I'm not quite sure I've got this right, but in your example you only want to have a single viewport in the LayoutDocumentPane at any time.

As far as I know, there isn't a way to stop a user moving windows around, into the document pane. So what I would do is probably download the source files for AvalonDock and create new type of LayoutPane (e.g. LayoutSingleDocumentPane) which could be used to host a single child, and doesn't allow the drag and drop operations.

I don't have an example of this, but I'm sure it would be possible to do.

FallLine