AvalonDock具有不同ObservableCollection的多个LayoutDocumentPane,其中包含动态创建的UserControls [英] AvalonDock multiple LayoutDocumentPane with different ObservableCollection containing dynamic created 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屋!