簡體   English   中英

如何將 ObservableCollection 綁定到 AvalonDock DocumentPaneGroup?

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

如果您只需要一個用於所有LayoutDocumentLayoutAnchorable容器的模板,您可以使用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>

解決方案 2:隱式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>

解決方案 3: DataTemplateSelector

使用隱式DataTemplate定義的先前解決方案可以替換為DataTemplateSelector DataTemplateSelector是另一個 WPF 概念,用於有選擇地應用DataTemplate
DataTemplateSelector是推薦的選擇,如果選擇DataTemplate可取決於多種復雜的約束,除了模型的數據單獨類型。 例如,它允許評估數據項並根據特定標准選擇適當的模板。

要定義模板選擇器,您必須擴展DataTemplateSelector ,它應該返回一個DataTemplate
最簡單的方法是使用x:KeyApp.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM