Saving Layout using linked docksites

Docking/MDI for WPF Forum

Posted 7 years ago by Bjørnar Sundsbø - Norway
Version: 12.2.0570
Platform: .NET 4.5
Environment: Windows 8 (64-bit)
Avatar

Hi

I'm currently working with saving and restoring layout in two windows. The DockSites are linked, and there are some strange artifacts in the current implementation:

In our implementation, we have two collections for DocumentWindows, and the same for ToolWindows. These collections contain ViewModels, and we have followed the example from the sample browser (using the attached behaviors).

We seem to have some slight problems when applying layout, where sometimes windows (document or tool) don't show up when layout is applied. I assume this is because the layout doesn't contain some of these windows, and they are therefore closed. I would like to keep them visible, without having to manipulate the xml string to place the items in the correct location before applying the layout. Other times they show up in both windows for some strange reason (could have been related to InvalidOperationException (enumeration was modified) when applying layout, though I think that was resolved when using Begin/EndUpdate on DeferredObservableCollection).

My next question would be: with two windows and linked docksites, would you recommend using the same DocumentItemsSource and ToolWindowItemsSource for both Docksites, or keep the solution as I have it, and move items between the lists, based on if they can be found in layout for either of the two windows.

Some of the items are usercontrols (there is a good reason behind this, though not a topic for this discussion), and that present a problem with existing parent when binding to the same list, however, I can probably work around that in DockSiteViewModelBehavior if they already have a parent. I don't currently know how I would work around it, but perhaps there is a way.

I'm sorry, but I don't have an example I can provide you with at the moment, but I guess for now I am mainly looking for directions when working with linked docksites.

[Modified 7 years ago]


Bjørnar Sundsbø

Comments (5)

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi, yes that can be tricky with linked dock sites since you don't really know which dock site last contained each of the items, other than examining the layout file manually.  If you can examine the layout data to see which view models are in which dock site, I would probably do what you mentioned and move items between the two lists based on if they are in the layout file or not.


Actipro Software Support

Posted 7 years ago by Bjørnar Sundsbø - Norway
Avatar

When the application starts, only a map is loaded (the viewmodel-usercontrol hybrid mentioned in the initial question). When the user logs in, layout is applied (lazy loaded) , BeginUpdate for collections and then add viewmodels, then EndUpdate. Any other order seems to either result in InvalidOperationException because some collection changed, or some windows being hidden (based on bug reports from test, this stil seems to be the problem, but I haven't had time to investigate). Based on the XmlDockSiteLayout from the loaded layout, I can now decide which collection to put ViewModels in.

There are two remaining issues:

  • Sometimes windows do not appear
  • Sometimes windows appear as duplicates
  • Items (map) that were in the DocumentItemsSource before layout is applied, are removed and never to be seen again, if they are not contained in the layout that was applied to the docksite.

Since the map is a visual loading different map services, it could take some time to load. Moving from one collection to another seem to results in the visual needing to load everything again, which takes time. I'm currently investigating an approach where I somehow hook into events for deserializing the layout, and MoveToLinkedDockSite before applying layout. The problem is that I don't know if I can do that before applying the layout (but will try that). My initial idea is at least that this would hopefully work, without having to destroy and recreate the DocumentWindow and it's children, and will simulate the original operation the user did to move the document in the first place.

Any additional suggestions based on the details here?

EDIT: MoveToLinkedDockSite did not work.

When mixing pattern for MVVM and serializing layout, there is a problem with directional docking. All dock locations are based on DefaultDock property used in context with DockSiteViewModelBehavior, and not where they are in the saved layout.

[Modified 7 years ago]


Bjørnar Sundsbø

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

Hi,

As for windows not appearing, most likely they aren't being found when you go to load the layout.  The "Layout Serialization" documentation topic talks about ways you can handle auto-creation of windows.  For instance, there is a DockingWindowDeserializing event you can listen to and see which windows are trying to be loaded.  That may help you debug what's going on.

Loading a layout will replace any windows that are currently open in the dock site.  That is by design.  If you want other windows to stay open that were not part of a layout being loaded, you'd need to call Open() on them again post-layout load.

The "MVVM Features" documentation topic talks about how you can enable a "Preserve Visuals" feature. That may help you with the visuals.

As for the default dock, my guess is that is related to the other issues you're having here.  Most likely a Track object for the related tool windows isn't being able to be loaded into the layout.  The Track is like a breadcrumb that tells it where to dock back to.  So if that isn't loading from the layout, thne it will fall back to the default dock.


Actipro Software Support

Posted 7 years ago by Bjørnar Sundsbø - Norway
Avatar

I use lazy loading so all windows don't have to be there initially. So far I haven't been able to reproduce the issue with missing windows that test reported, and it may not be an issue anymore. I will look into the event so I can debug.

I have realized that loading layout will replace any existing items, and I have handeled that. I don't believe that is an issue anymore. I also use ItemsContainerRetentionMode to sort out visuals, assuming that is what you meant.

As for the duplicate windows, I have been able to reproduce it most of the time using the following pattern:

ApplyLayout();
ArrangeMaps();
BeginUpdate();
// Add document viewmodels to correct collection based on details in layout
documents.ForEach(AddDocumentViewModel);
// Add toolwindows to correct collection
toolwindows.ForEach(AddToolWindowViewModel);
EndUpdate();

When moving a document from one screen to the other, save layout and perform the code above again/or restart the application, the window I last moved shows up as a duplicate. Selecting one selects both. In the layout, the document is only present once. In the area where they are located, there are two documents (DocumentRef) and a Track (in layout). In the docksite, I have three documentwindows, where one is a duplicate. Restarting the application a couple of times seems to resolve it.

I also tried applying layout, and then arranging maps, but apparently with the same result. At least Dock orientation is still not correct. It makes sense that first applying the layout, and then adding windows would probably result in the toolwindow using dock orientation from the viewmodel. Using the following approach still results in the same:

BeginUpdate();
documents.ForEach(AddDocumentViewModel);
toolwindows.ForEach(AddToolWindowViewModel);
ApplyLayout();
ArrangeMaps();
EndUpdate();

If applying the layout after EndUpdate, I always get InvalidOperationException because of modified collection. Same if I try to close windows outside of Begin/EndUpdate when logging off.

Additional stuff is that when moving a document from one window to the other, the original window seem to remain on the first docksite, and I have to close it manually when I log off. Perhaps I need to destroy them instead? Could of course be related. I don't know if when the user drags a window to another docksite, if I should move the window in the *ItemsSource as well?

I might see if I can create a sample to reproduce these things, but hopefully you can provide me with additional help based on the details I have provided? I will at least see if I can use the event to help me debug. To solve the dock location issue, I might extend the layout manager to add additional  details in the serialized data, and add information about dock location so I can assign location to viewmodels before adding them to the collections.

But duplicate or missing windows has priority, so hopefully you are correct in your guess.

EDIT:
Duplicate window was the result of a window that was moved from one docksite to another, and when clearing *ItemsSource for where the item exists doesn't close/dispose the window. Seems like the DockSite forgets about items in its ItemsSource when windows are moved to linked DockSite. Is this a bug (maybe it makes sense for non-linked docksites, but perhaps not for linked)? I have worked around this, though it is a bit inconvenient that I have to, since I think that perhaps the DockSite should take care of this since it was created based on the ItemsSource

[Modified 7 years ago]


Bjørnar Sundsbø

Posted 7 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar

You would want to remove the documents from your ItemsSource when it moves to another dock site since I don't believe we modify the ItemsSource objects ourselves, so it must be done on your end.

As for the missing windows, I'm not really sure what's happening there because in more normal circumstances it all works fine.  The only reason something would be missing is if it's not able to match up what it's looking for.  Hopefully by debugging with that event I mentioned (maybe also visually taking a look at the XML source of the layout file too) and looking at what documents you have available, you can figure out where things are going wrong.

But the end point is that you do want to make sure your ItemsSource collections in each dock site have unique instances of documents.

For the duplicate window issue, if you want to make a new simple sample project that shows the problem, you can email that to our support address and reference this thread.  Try to keep the project as minimial as possible so it's easy to debug, and rename the .zip file extension so it doesn't get spam blocked.  Thanks!


Actipro Software Support

The latest build of this product (v2019.1 build 0681) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.