Search code examples
c#wpfavalondock

Save AvalonDock layout with dynamic content


I am trying to learn the AvalonDock environment in WPF. I have an anchorable pane that contains a treeview which displays a list of objects (basically contains a name and value).

I also have some document panes that host a UserControl. I can drag an item from the treeview into a document (UserControl which is basically a WrapPanel) and then drop it, it adds a 2nd user control type (this user control has a textblock bound to 'name' and a textbox bound to 'value') to my control hosted by the document.

Now - I want to be able to save this layout- with the dynamic content created by the drag/drop.

Is this possible? When using the XmlLayoutSerializer I see the generated xaml has my documents and anchorables, but none of these items have any content.

Should I instead be saving a collection of the objects (i.e. the ObservableCollection I am bound to) and initialize the collection when I want to 'restore' the view?

The intent is to have a view that end-users can modify to display the data they want (from the treeview) and arrange the layout as they see fit.

Thanks for any pointers


Solution

  • There's an article on CodeProject which describes a solution: https://www.codeproject.com/articles/719143/avalondock-tutorial-part-load-save-layout

    You may also take a look at the Gemini project, which has a much more flexible solution: https://github.com/tgjones/gemini/ The important stuff is in the Gemini/Framework directory.

    It's a pure MVVM solution which keeps all the documents and layout items in the main/shell viewmodel and databinds to it. While saving layout, it asks every viewmodel to save its state and the DockingManager state is persisted last. While loading layout, all the state is read first and the viewmodels are recreated in the LayoutSerializationCallback event of the AvalonDocks XmlLayoutSerializer. This is nice and clean approach, but (AFAIK) it cannot handle a situation when the controls are created purely in XAML and connected to the rest of the application using some kind of messaging (Prism EventAggregator for example).

    To solve this kind of problem, you'll need a help from the view which hosts DockingManager, ask it for a list of LayoutAnchorables and LayoutDocuments and save/load their states using the similar mechanism. It's not as elegant and pure MVVM as the original solution, but I found it more flexible. You can wrap everything in a few interfaces and extension methods.

    I did something like that for my project and it works great. Might put it on GitHub some day.