繁体   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