AvalonDock具有不同ObservableCollection的多个LayoutDocumentPane,其中包含动态创建的UserControls [英] AvalonDock multiple LayoutDocumentPane with different ObservableCollection containing dynamic created UserControls

查看:96
本文介绍了AvalonDock具有不同ObservableCollection的多个LayoutDocumentPane,其中包含动态创建的UserControls的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于AvalonDock的UI,其中至少包含三个静态LayoutDocumentPanes.如何动态地用不同的UserControl集合填充这些窗格?我发现,可以为整个DockingManager设置 DocumentSource ,然后可以使用此Collection来为所有窗格生成元素.

I have a AvalonDock based UI with at least three static LayoutDocumentPanes. How can i dynamically fill those Panes with different UserControl Collections? I figured out, that i can set a DocumentSource for the whole DockingManager and this Collection then can be used to generate elements for all panes.

我可以使用多个源集合,还是可以为每个LayoutDocumentPane过滤我的集合?

Can I use multiple source collections or can i filter my collection for each LayoutDocumentPane?

<xcad:DockingManager  
            DocumentsSource="{Binding MyUserControls1}">
          
            <xcad:DockingManager.Resources>
                <DataTemplate DataType="{x:Type local:MyUserControl}">
                        <local:MyUserControl/>   
                </DataTemplate>
            </xcad:DockingManager.Resources>

    <xcad:LayoutRoot>
        <xcad:LayoutPanel Orientation="Horizontal" >
            <xcad:LayoutPanel Orientation="Vertical" DockWidth="6*">
                <xcad:LayoutPanel Orientation="Horizontal">
                            <xcad:LayoutDocumentPaneGroup>
                                <xcad:LayoutDocumentPane>
                                <!-- UserControls from ObservableCollection 1-->
                                </xcad:LayoutDocumentPane>
                            </xcad:LayoutDocumentPaneGroup >
                            <xcad:LayoutDocumentPaneGroup>
                                <xcad:LayoutDocumentPane >
                                <!-- UserControls from ObservableCollection 2-->
                                </xcad:LayoutDocumentPane>
                            </xcad:LayoutDocumentPaneGroup >
                            <xcad:LayoutDocumentPaneGroup>
                                <xcad:LayoutDocumentPane >
                                <!-- UserControls from ObservableCollection 3-->
                                </xcad:LayoutDocumentPane>
                            </xcad:LayoutDocumentPaneGroup >
                </xcad:LayoutPanel>
            </xcad:LayoutPanel>
        </xcad:LayoutPanel>
     </xcad:LayoutRoot>

推荐答案

要动态控制布局,您必须实现 ILayoutUpdateStrategy 并将其分配给 DockingManager.LayoutUpdateStrategy .将项目添加到 DockingManager.DocumentsSource DockingManager.AnchorablesSource 时,都会调用此策略.您可以在添加内容之前或之后处理布局细节.

To control the layout dynamically, you have to implement ILayoutUpdateStrategy and assign it to DockingManager.LayoutUpdateStrategy. This strategy is invoked when ever you add an item to either DockingManager.DocumentsSource or DockingManager.AnchorablesSource. You can handle layout details before or after the adding of the content.

请注意,每个文档模型仍然需要单独的 DataTemplate (请参见示例). ILayoutUpdateStrategy 仅处理布局,而不处理内容呈现.

Note that an individual DataTemplate for each document model is still required (see examples). ILayoutUpdateStrategy only handles layout, but not content rendering.

您必须将所有不同类型的文档添加到公共源集合中.
我建议引入一个接口,例如 IDocument ,该接口必须由每种文档类型实现.这样可以将它们存储在 IDocument 类型的通用集合中,并在迭代该集合时启用多态性.
然后,您可以将 ObservableCollection< IDocument> 绑定到 DockingManager.DocumentsSource .

You have to add all documents of different type to a common source collection.
I recommend to introduce an interface e.g., IDocument which is required to be implemented by each document type. This allows to store them in a common collection of type IDocument and enables polymorphism when iterating the collection.
You can then bind a ObservableCollection<IDocument> to the DockingManager.DocumentsSource.

以下示例还创建了所需的布局(由于分组约束).因为它将添加错误的布局元素到 DockingManager.Layout LayoutPanel 中,所以在添加内容之前 处理该布局.因此,对于分组的文档,无需预先定义 LayoutRoot :

The following example also creates the required layout (due to the grouping constraint). Because it will add mising layout elements to the LayoutPanel of DockingManager.Layout, the layout is handled before the content is added. Therefore in case of the grouped documents, there is no need to predefine the LayoutRoot:

LayoutUpdateStrategy.cs

public class LayoutUpdateStrategy : ILayoutUpdateStrategy
{
  #region Implementation of ILayoutUpdateStrategy

  public bool BeforeInsertAnchorable(
    LayoutRoot layout,
    LayoutAnchorable anchorableToShow,
    ILayoutContainer destinationContainer)
  {
    return false;
  }

  public void AfterInsertAnchorable(LayoutRoot layout, LayoutAnchorable anchorableShown)
  {
  }

  // Creates a new LayoutDocumentPane for each document model type.
  // All grouped documents will reside in a common LayoutDocumentPaneGroup.
  public bool BeforeInsertDocument(
    LayoutRoot layout,
    LayoutDocument documentToShow,
    ILayoutContainer destinationContainer)
  {
    if (destinationContainer?.FindParent<LayoutFloatingWindow>() != null)
    {
      // Return 'false' as the strategy hasn't performed any action
      return false;
    }

    LayoutDocumentPane existingDocumentsPane = layout.Descendents().OfType<LayoutDocumentPane>().FirstOrDefault(
      pane => pane.Children.Any(
        layoutDocument => layoutDocument.Content.GetType() == documentToShow.Content.GetType()));

    if (existingDocumentsPane != null)
    {
      existingDocumentsPane.Children.Add(documentToShow);
    }
    else
    {
      // Get the existing LayoutDocumentPaneGroup
      LayoutDocumentPaneGroup paneGroup = layout.Descendents().OfType<LayoutDocumentPaneGroup>().FirstOrDefault();

      // Create a new LayoutDocumentPaneGroup if there is none in the current layout
      if (paneGroup == null)
      {
        paneGroup = new LayoutDocumentPaneGroup();
        layout.RootPanel.Children.Add(paneGroup);
      }

      // Create a new LayoutDocumentPane for the new document type
      var pane = new LayoutDocumentPane(documentToShow);
      paneGroup.Children.Add(pane);
    }

    // Return 'true' as the strategy has performed any action
    return true;
  }

  public void AfterInsertDocument(LayoutRoot layout, LayoutDocument documentToShow)
  {
  }

  #endregion
}

MainWindow.xaml

<Window>
  <DockingManager DocumentsSource="{Binding MyDocuments}">
    <DockingManager.LayoutUpdateStrategy>
        <LayoutUpdateStrategy />
      </DockingManager.LayoutUpdateStrategy>
  </DockingManager>
</Window>
          

这篇关于AvalonDock具有不同ObservableCollection的多个LayoutDocumentPane,其中包含动态创建的UserControls的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆