How to get the "last active" Document Window using MVVM

Docking/MDI for WPF Forum

Posted 4 years ago by Eric P
Version: 16.1.0630
Avatar

I have several Tool Windows and several Document Windows. For now each Document Window contains the same content (in my case it’s a map). My project is also using the MVVM pattern and an event bus (Event Aggregator) to send events/messages between each of the View Models. I have a Tool Window that contains a button that is supposed to tell the “active” Document Window to do something. For this example I want the map to zoom to a specific location. Since the button is on a Tool Window it becomes IsActive=true at the time the button is clicked. Thus all of the Document Windows are IsActive=false. If all of the Document Windows are docked on top of each other I can check the IsSelected to know which Document Window should reposed to the event. If two or more of the Document Windows are docked side-by-side then both are IsActive=false and IsSelected=true at the time of the button click in the Tool Window. I cannot tell which Document Window should respond to the event.

I believe that the DockSite might be able to tell the difference somehow and I might be able to use the LastActiveDateTime and get the most recently active/selected Document Window. The problem here is each Document Window does not know about the others and my ViewModels do not have any reference to the DockSite. The Document Windows need to know if they should respond to the event based on their current “state”. I was hoping that a combination of IsOpen, IsActive, and IsSelected would be enough but in the case where two or more are docked side-by-side I can’t tell which one should respond to the event.

Any suggestions would be greatly appreciated.

Thanks,
-eric

Comments (5)

Posted 4 years ago by Eric P
Avatar

Ok I was looking through the documentation again and the DockSite has a property called PrimaryDocument. If I understand this correctly this will always be the last active DocumentWindow, right? I guess technically this will be null when there are no Document Windows? What about adding a bind-able Boolean property to DocumentWindow called IsPrimary or IsPrimaryDocument (similar to IsOpen and IsActive). Then each Document View Model can bind to this property and they will know if they are the primary document without knowing anything about each other. What do you think?

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

Hi Eric,

Correct, the DockSite.PrimaryDocument property will tell you which document is effectively the last active document, even if another tool window is active at the time.  Check out the "Working with Documents" topic in the documentation for more info.

As for the additional view-model property, we can write down the idea for that.  Those properties get a bit tricky to sync around, so there would need to be a large benefit to adding it.  You can't just compare the DocumentWindow with DockSite.PrimaryDocument?


Actipro Software Support

Posted 4 years ago by Eric P
Avatar

I understand that the DockSite knows which document is primary but the view models know nothing about the DockSite. As far as I understand it this is basic MVVM. I realize that I could add some code-behind to track the primary document (using its changed event) and then find the matching Document View Model and set a property on that view model. I could also add a behavior, like your older DockSiteBehavior, that would do the same job. Neither of these approaches violate MVVM and we are willing to use this approach. I just thought adding a bindable IsPrimary property, like the other IsOpen, IsActive, and IsSelected properties, would be a nice addition and make the DockSite even more MVVM friendly. Adding a property like IsPrimary seems very logical to me. It's more "state" information like IsOpen, IsActive, and IsSelected that the bindable view models need to know. In short we can make it work without an IsPrimary property but adding this property would make the dock site even more MVVM friendly. If you guys decide to add an IsPrimry property how long would it take to be in the API?

Posted 4 years ago by Eric P
Avatar

So I ended up adding the following code-behind.

private void dockSite_PrimaryDocumentChanged(object sender, DockingWindowEventArgs e) {
  foreach (DockingItemViewModelBase dockingItemViewModel in ((DockSite)sender).DocumentItemsSource) {
    dockingItemViewModel.IsPrimary = (e.Window != null && dockingItemViewModel == e.Window.DataContext);
  }
}

I also added an IsPrimary boolean property to my View Model.

If there was a bindable IsPrimary property we could do the following which would require no code-behind.

<Style TargetType="docking:DockingWindow">
  <Setter Property="IsActive" Value="{Binding Path=IsActive, Mode=TwoWay}" />
  <Setter Property="IsOpen" Value="{Binding Path=IsOpen, Mode=TwoWay}" />
  <Setter Property="IsSelected" Value="{Binding Path=IsSelected, Mode=TwoWay}" />
  <Setter Property="IsPrimary" Value="{Binding Path=IsPrimary, Mode=TwoWay}" />
</Style>

 Just something to consider.

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

Hi Eric,

Thanks, I've written down this info on the TODO list.  I can't give an estimate on timeframe since we have to prioritize it with our other work.  Your workaround solution looks solid and I would recommend doing that for now.


Actipro Software Support

The latest build of this product (v2019.1 build 0683) 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.