如何解决content presenter不显示view?

How to resolve content presenter not displaying View?

我已将内容展示器添加到我的 TabControl 的数据模板中,以显示正确的视图。

但是当我加载应用程序时,选项卡显示但没有用户控制内容。

我用 Google 搜索了这个错误并发现了这个 solution,这表明数据上下文有错误,但在我的 AppVM 和下面的 AppView 中设置似乎没问题。

我在 AppView 中引用的 VM 和视图的名称也是正确的。

有人知道这里的设置哪里出了问题吗?

这是包含两个视图的 ApplicationView:

<Window x:Class="MongoDBApp.Views.ApplicationView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:views="clr-namespace:MongoDBApp.Views"
        xmlns:vm="clr-namespace:MongoDBApp.ViewModels"
        Title="ApplicationView"
        Width="800"
        Height="500">

    <Window.Resources>
        <DataTemplate DataType="{x:Type vm:CustomerDetailsViewModel}">
            <views:CustomerDetailsView />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CustomerOrdersViewModel}">
            <views:CustomerOrdersView />
        </DataTemplate>
    </Window.Resources>

    <Window.DataContext>
        <vm:ApplicationViewModel />
    </Window.DataContext>


    <TabControl ItemsSource="{Binding PageViewModels}" TabStripPlacement="Top">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentPresenter Content="{Binding CurrentPageViewModel}" />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Window>

ApplicationViewModel 构造函数和相关字段:

private ICommand _changePageCommand;
private IPageViewModel _currentPageViewModel;
private List<IPageViewModel> _pageViewModels;
private static ICustomerDataService customerDataService = new CustomerDataService(CustomerRepository.Instance);




#endregion

/// <summary>
/// Initializes a new instance of the <see cref="ApplicationViewModel"/> class.
/// </summary>
public ApplicationViewModel()
{
    // Add available pages
    PageViewModels.Add(new CustomerDetailsViewModel(customerDataService));
    PageViewModels.Add(new CustomerOrdersViewModel());

    // Set starting page
    CurrentPageViewModel = PageViewModels[0];
}

我们通常不会在 ControlTemplate 之外使用 ContentPresenter,当然也不会像您在 DataTemplate 中所做的那样...使用 ContentPresenter 将使 WPF 框架搜索与 Content 的类型相匹配的 DataTemplate,因此在您的情况下,您将以无限循环结束。相反,您应该将关联视图放在 DataTemplate:

<DataTemplate DataType="{x:Type YourDataXamlPrefix:CurrentPageViewModel}">
    <YourUiXamlPrefix:YourView DataContext="{Binding CurrentPageViewModel}" />
</DataTemplate>

这样,当框架在集合中遇到您的视图模型class时,它会找到这个DataTemplate并渲染相关视图。

ContentTemplate 属性 包装 Content 对象。

例如,在您的代码中,您将 .Content 属性 设置为 CustomerDetailsViewModel 对象,并尝试绑定到该对象的 CurrentPageViewModel,这不存在。

正在渲染的是:

<TabControl>
    <TabItem>
        <ContentPresenter Content=CustomerDetailsViewModel>
            <ContentPresenter Content="{Binding CurrentPageViewModel}" />
        </ContentPresenter>
    </TabItem>
    <TabItem>
        <ContentPresenter Content=CustomerOrdersViewModel>
            <ContentPresenter Content="{Binding CurrentPageViewModel}" />
        </ContentPresenter>
    </TabItem>
</TabControl>

因为 TabControl 会自动生成一个 ContentPresenter 来包装每个 TabItem.Content,你根本不需要这个模板。

但听起来您真正想要的是绑定 TabControl

SelectedItem 属性
<TabControl ItemsSource="{Binding PageViewModels}" 
            SelectedItem="{Binding CurrentPageViewModel}"
            TabStripPlacement="Top">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Name}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>