[英]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.