[英]How do I bind an ObservableCollection to an AvalonDock DocumentPaneGroup?
我需要在 AvalonDock 2.0 中加载一组项目作为文档。 这些对象从一个抽象类继承,我想根据子类在文档中呈现一个框架。
这是我的 XAML:
<ad:DockingManager Background="Gray" DocumentsSource="{Binding Path=OpenProjects}"
ActiveContent="{Binding Path=CurrentProject, Mode=TwoWay}">
<ad:DockingManager.DocumentHeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=OpenProjects/Name}" />
</DataTemplate>
</ad:DockingManager.DocumentHeaderTemplate>
<ad:DockingManager.LayoutItemTemplate>
<DataTemplate>
<Grid>
<Grid.Resources>
<DataTemplate DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</Grid.Resources>
</Grid>
</DataTemplate>
</ad:DockingManager.LayoutItemTemplate>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
到目前为止,我已经实现了显示与OpenProjects
集合中项目一样多的文档,但我似乎无法在每个文档中显示任何内容。
另外,我不知道我是否正确使用ActiveContent
:我想将当前活动文档上分配的 ViewModel 分配给CurrentProject
。
感谢您的时间。
您无法看到任何内容的原因是您定义LayoutItem
模板的方式。 这是行不通的。
还可以考虑使用自定义控件而不是Frame
。 Frame
很重。 除非您不需要显示 HTML,否则请避免使用此控件。 内容导航非常容易实现,以防您想显示可导航的内容。 只需将您的文档内容包装到UserControl
。
您正在正确使用ActiveContent
属性。
要解决您的问题,您有三个推荐的解决方案,其中第一个不完全满足您的要求。 既然你定义了DockingManager.LayoutItemTemplate
错误,我还是会展示它。
LayoutItemTemplate
如果您只需要一个用于所有LayoutDocument
和LayoutAnchorable
容器的模板,您可以使用DockingManager.LayoutItemTemplate
属性。 此属性接受单个DataTemplate
。 WPF 通常不支持嵌套的DataTemplate
定义,就像在您的代码中一样。
<ad:DockingManager>
<ad:DockingManager.LayoutItemTemplate>
<DataTemplate>
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
</ad:DockingManager.LayoutItemTemplate>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane />
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
DataTemplate
在更高级的场景中,您会根据不同的模型显示不同的视图。 如果显示的内容仅取决于模型的数据类型(如您的情况),则推荐的方法是提供隐式DataTemplate
定义。
WPF 将自动将隐式DataTemplate
应用于与此模板的DataTemplate.TargetType
匹配的每个数据类型。
如果未分配显式x:Key
值,则DataTemplate
是隐式的。 为确保DataTemplate
能够真正自动应用, DataTemplate
还必须定义在与目标类型相同的资源范围内。 例如,在App.xaml 的Application.Resources
中定义DataTemplate
将使模板在应用程序范围内自动应用。
<ad:DockingManager>
<ad:DockingManager.Resources>
<DataTemplate DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</ad:DockingManager.Resources>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
DataTemplateSelector
使用隐式DataTemplate
定义的先前解决方案可以替换为DataTemplateSelector
。 DataTemplateSelector
是另一个 WPF 概念,用于有选择地应用DataTemplate
。
甲DataTemplateSelector
是推荐的选择,如果选择DataTemplate
可取决于多种复杂的约束,除了模型的数据单独类型。 例如,它允许评估数据项并根据特定标准选择适当的模板。
要定义模板选择器,您必须扩展DataTemplateSelector
,它应该返回一个DataTemplate
。
最简单的方法是使用x:Key
在App.xaml资源字典中定义模板,然后根据条件从中进行选择。
DockingManger
通过分配DockingManager.LayoutItemTemplateSelector
属性DockingManger
接受模板选择器:
应用程序.xaml
使用x:Key
定义显式DataTemplate
:
<Application.Resources>
<DataTemplate x:Key="SubclassAViewModelTemplate" DataType="{x:Type vm:SubclassAViewModel}">
<Frame Source="Pages/SubclassAProject.xaml" />
</DataTemplate>
<DataTemplate x:Key="SubclassBViewModelTemplate" DataType="{x:Type vm:SubclassBViewModel}">
<Frame Source="Pages/SubclassBProject.xaml" />
</DataTemplate>
<DataTemplate x:Key="SubclassCViewModelTemplate" DataType="{x:Type vm:SubclassCViewModel}">
<Frame Source="Pages/SubclassCProject.xaml" />
</DataTemplate>
</Application.Resources>
DocumentManagerTemplateSelector.cs
以下代码使用自 C# 8.0 起可用的 Switch 表达式。 它可以替换为 switch 语句或级联的 if 语句。
class DocumentManagerTemplateSelector : DataTemplateSelector
{
#region Overrides of DataTemplateSelector
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
return item switch
{
SubclassAViewModel _ => Application.Current.Resources["SubclassAViewModelTemplate"] as DataTemplate,
SubclassBViewModel _ => Application.Current.Resources["SubclassBViewModelTemplate"] as DataTemplate,
SubclassCViewModel _ => Application.Current.Resources["SubclassCViewModelTemplate"] as DataTemplate,
_ => base.SelectTemplate(item, container)
};
}
#endregion
}
主窗口.xaml
<ad:DockingManager>
<xcad:DockingManager.LayoutItemTemplateSelector>
<local:DocumentManagerTemplateSelector />
</xcad:DockingManager.LayoutItemTemplateSelector>
<ad:LayoutRoot>
<ad:LayoutPanel>
<ad:LayoutDocumentPaneGroup>
<ad:LayoutDocumentPane>
</ad:LayoutDocumentPane>
</ad:LayoutDocumentPaneGroup>
</ad:LayoutPanel>
</ad:LayoutRoot>
</ad:DockingManager>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.