Frage

I use AvalonDock with MVVM in a WPF project.

When I hit the "X" (Close button of the tab) my document closes but stays in memory. It seems that it is only hidden. It is not removed from my Model.Documents collection.

If I add DockingManager_DocumentClosing and try to remove my document from the collection, I receive an Exception in the following method of Xceed.Wpf.AvalonDock.Layout.LayoutContent because parentAsContainer is null.

/// <summary>
/// Close the content
/// </summary>
/// <remarks>Please note that usually the anchorable is only hidden (not closed). By default when user click the X button it only hides the content.</remarks>
public void Close()
{
    var root = Root;
    var parentAsContainer = Parent as ILayoutContainer;
    parentAsContainer.RemoveChild(this);
    if (root != null)
        root.CollectGarbage();
    OnClosed();
}

Does anybody know how I could manage document in AvalonDock that can be removed from my Model.Documents in order to be eventually be disposed when I hit its Close button?

For reference: This is my XAML of the AvalonDock:

<avalonDock:DockingManager
    x:Name="DockingManager" 
    DocumentsSource="{Binding DocumentItems}"  
    ActiveContent="{Binding ActiveMainWindowViewModel,
        Converter={StaticResource RestrictedClassConverter},
        ConverterParameter={x:Type multiSimAnalysis:MainWindowViewModel},
        Mode=TwoWay}"
    DocumentClosing="DockingManager_DocumentClosing"
    ActiveContentChanged="DockingManager_ActiveContentChanged">

  <avalonDock:DockingManager.LayoutItemContainerStyleSelector>
    <pane:PanesStyleSelector>
      <pane:PanesStyleSelector.MainWindowViewLcStyle>
        <Style TargetType="{x:Type avalonDock:LayoutItem}">
          <Setter Property="Title" Value="{Binding Model.Title}"/>
          <Setter Property="ToolTip" Value="{Binding Model.Title}"/>
          <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
          <Setter Property="IconSource" Value="{Binding Model.IconSource}"/>
          <Setter Property="IsSelected" Value="{Binding Model.IsSelected, Mode=TwoWay}"/>
          <Setter Property="IsActive" Value="{Binding Model.IsActive, Mode=TwoWay}"/>
          <Setter Property="ContentId" Value="{Binding Model.ContentId}"/>
        </Style>
      </pane:PanesStyleSelector.MainWindowViewLcStyle>
    </pane:PanesStyleSelector>
  </avalonDock:DockingManager.LayoutItemContainerStyleSelector>

  <avalonDock:DockingManager.LayoutItemTemplateSelector>
    <multiSimAnalysis:PanesTemplateSelector>
      <multiSimAnalysis:PanesTemplateSelector.MainWindowLcTemplate>
        <DataTemplate>
          <multiSimAnalysis:MainWindowViewLc /> 
        </DataTemplate>
      </multiSimAnalysis:PanesTemplateSelector.MainWindowLcTemplate>
    </multiSimAnalysis:PanesTemplateSelector>
  </avalonDock:DockingManager.LayoutItemTemplateSelector>

  <avalonDock:DockingManager.Theme>
    <avalonDock:VS2010Theme/>
  </avalonDock:DockingManager.Theme>
  <avalonDock:LayoutRoot>
    <avalonDock:LayoutPanel Orientation="Horizontal">
      <avalonDock:LayoutAnchorablePane DockWidth="400">
        <avalonDock:LayoutAnchorable Title="Scope(s) selection" x:Name="PanelScopeSelection" IsVisible="True">
          <scopeSelection:UserControlSelectStudyScope x:Name="ToolScopeSelection"/>
        </avalonDock:LayoutAnchorable>
      </avalonDock:LayoutAnchorablePane>
      <avalonDock:LayoutDocumentPane/>
      <avalonDock:LayoutAnchorablePane DockWidth="150">
        <avalonDock:LayoutAnchorable Title="Properties" x:Name="PanelScopePropertyGrid">
          <!--<multiSimAnalysis:UserControlPropertyGrid x:Name="ToolPropertyGrid"  />-->
          <xctk:PropertyGrid x:Name="ToolPropertyGrid" SelectedObject="{Binding ActiveObject}" />
        </avalonDock:LayoutAnchorable>
      </avalonDock:LayoutAnchorablePane>
    </avalonDock:LayoutPanel>
  </avalonDock:LayoutRoot>
</avalonDock:DockingManager>
War es hilfreich?

Lösung

I actually find an unacceptable workaround. It is really twisted.

I only give that as reference. There should be a clean way to do it.

    // ************************************************************************
    private void DockingManager_DocumentClosing(object sender, Xceed.Wpf.AvalonDock.DocumentClosingEventArgs e)
    {
        e.Document.CanClose = false;

        DocumentModel documentModel = e.Document.Content as DocumentModel;
        if (documentModel != null)
        {
            Dispatcher.BeginInvoke(new Action(() => this.Model.DocumentItems.Remove(documentModel)), DispatcherPriority.Background);
        }
    }

Andere Tipps

I have found that on a LayoutDocument or a LayoutAnchorablePane, applying both this setting works: CanClose="False" or CanFloat="False".

It removes the Close button.

<avalonDock:LayoutDocument Title="Board"
                           ContentId="Board"
                           CanClose="False"
                           CanFloat="False">
</avalonDock:LayoutDocument>

Register for IsVisibleChanged.

void layoutFPR_Hidden(object sender, EventArgs e)
{
    LayoutAnchorable window = (LayoutAnchorable)sender;
    YourClass content = window.Content as YourClass;

    // Close the object
    content = null;
    ((LayoutAnchorable)sender).Close();

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top