質問

I have a control that utilizes an AvalonDock (2.0) DockingManager control for displaying a set of documents managed by an underlying view model:

<avalonDock:DockingManager DocumentsSource="{Binding Items}">
    <avalonDock:DockingManager.LayoutItemContainerStyle>
        <Style TargetType="{x:Type avalonDockControls:LayoutItem}" BasedOn="{StaticResource DocumentItem}"/>
    </avalonDock:DockingManager.LayoutItemContainerStyle>
    <avalonDockLayout:LayoutRoot>
        <avalonDockLayout:LayoutPanel Orientation="Horizontal">
            <avalonDockLayout:LayoutDocumentPane/>
        </avalonDockLayout:LayoutPanel>
    </avalonDockLayout:LayoutRoot>
</avalonDock:DockingManager>

The document view model has an IsSelected property, and when the view model is selected, I want to select and show the document in the DockingManager. To do this, I updated the Style for LayoutItem as follows:

<Style x:Key="DocumentItem" TargetType="{x:Type avalonDockControls:LayoutItem}">
    <Setter Property="Title" Value="{Binding Model.TabTitle}"/>
    <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
</Style>

This approach works fine when the control is hosted within a WPF application, but when the control is hosted within a VSPackage, selecting the document in the view model more often than not does not bring the selected document into view. In the image below, the user clicked on the Customer node to edit, but the customer document did not come into view.

AvalonDock issue

The view model layer is setting IsSelected as expected, and when the control utilized a TabControl, the selected document always showed on top.

It appears to be an issue within AvalonDock. What I am finding is when a LayoutItem is selected via the view model, the first document in the list is being reselected to true at the LayoutDocument/LayoutContent/LayoutElement layer, which trickles back up and resets IsSelected to true at the LayoutItem layer. I would love to bind IsSelected to my view model at the LayoutDocument/LayoutContent/LayoutElement layer, but there is no DependencyProperty at that layer.

I've tried alternate ways of binding IsSelected to my view model, but so far without success. Has anyone else run into this issue? Know of any workarounds or other approaches? I'd hate to resort to having to using a non MVVM approach, just to do document selection.

Edit: It seems like this issue may by obscure, as I'm having difficulty creating a reproducing test case, even with a VSPackage. In the following test case that simulates the actual controls with dual ToolWindows and Mediator messages, the document selection works fine.

Tool Windows

This test case (with a WPF app and a VSPackage) is available here (click on Tools=>My command name to launch tool windows, and enter a document title in one window to choose or create and select a document in the window with the DockingManager).

役に立ちましたか?

解決

I'm putting a bounty on this one, as I'm sure others will run into this issue one way or another, and there should be a better solution.

At the moment, I have a horrible hack to get document selection to work:

  1. I maintained the same IsSelected binding to my document view model in the LayoutItem style.
  2. In my main view model, I added a SelectedItem property to track which document is selected programatically (by an edit event, etc.).
  3. I added an event handler for ActiveContentChanged on the DocumentManager control, and in this method I reselect the SelectedItem in my view model if it is not selected. AvalonDock tries up to a half dozen times to reselect the first document in the list before giving up!
  4. I added an event handler for PreviewMouseDown on the DocumentManager control, and in this method I null the view model SelectedItem so that user initiated selection continues to work.

Again, looking for a better answer to this!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top