为WPF TabControl配置动态标头

问题描述 投票:0回答:1

我正在尝试创建一个基本的窗口,该窗口使用WPF TabControl允许用户添加新的选项卡。我希望最终产品看起来像选项卡在Web浏览器中的工作方式,其中最后一个选项卡只是一个“ +”,单击该选项将添加一个新的选项卡。

我正在尝试编写XAML代码来进行设置,发现我可以在“ TabControl.Resources”中指定多个DataTemplate,并且根据“ DataType”,正确的DataTemplate将用于显示每个选项卡的正确视图...但是在处理选项卡标题时,我只能为“ TabControl.ItemTemplate”

指定一个DataTemplate

这是我到目前为止所拥有的:

<TabControl ItemsSource="{Binding Tabs}">
    <TabControl.Resources>

        <!-- If the tab is of type "TabViewModel" I want this content -->
        <DataTemplate DataType="x:Type vm:TabViewModel">
            <!-- TabView is defined as a separate user control -->
            <v:TabView/>
        </DataTemplate>

        <!-- If the tab is of type "NewTabViewModel" I want this content -->
        <DataTemplate DataType="x:Type vm:NewTabViewModel">
            <!-- NewTabView is defined as a separate user control -->
            <v:NewTabView/>
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemTemplate>
        <!-- if the tab is of type "TabViewModel" I want this header -->
        <DataTemplate DataType="x:Type vm:TabViewModel">
            <TextBlock Text="{Binding Name}"/>
        </DataTemplate>

        <!-- If the tab is of type "NewTabViewModel" I want this header -->
        <!-- ERROR: Adding a second "DataTemplate" here results in an error -->
        <DataTemplate DataType="x:Type vm:NewTabViewModel">
            <TextBlock Text="+"/>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>

[Google周围的地方,我发现了一些有关设置TemplateSelector并编写大量背景C#代码的文章,但是对于这种简单的操作来说,这似乎太过分了。我只希望它显示选项卡名称,如果它是常规的TabViewModel对象,则显示“ +”,如果它是NewTabViewModel对象。

c# wpf xaml tabcontrol
1个回答
0
投票

这里有DataTemplate的两种完全不同的用法。

ItemTemplate属性的类型为DataTemplate。具体来说,是一个DataTemplate,而不是一个集合。期望您将其设置为所需的任何模板,这就是它将用于填充选项卡标题的模板。此外,在TabControl的情况下,该模板将应用于all标头;您不必在每个标签上进行更改。

选项卡面板本身的类型为ContentControl,每个面板都绑定到一个视图模型。 ContentControl包含一个ContentPresenter,它遍历逻辑树,为它绑定到的数据类型寻找一个DataTemplate(在内部,DataTemplate的DataType属性只是将类型本身设置为x:Key的语法糖)。

[您的问题是,您希望像提供ResourceDictionary一样使用ItemTemplate,指定多个DataTemplate,但希望您提供模板本身,而只能提供一个。因此,要实现您要执行的操作,只需给它提供一个DataTemplate并用ContentPresenter(由Dreamer建议)填充它,就如同选项卡面板本身一样。这个ContentPresenter有自己的ResourceDictionary,您可以在其中放置标题模板:

<TabControl ItemsSource="{Binding Tabs}">

    <TabControl.Resources>

        <!-- Panel templates -->

        <DataTemplate DataType="{x:Type vm:TabViewModel}">
            <v:TabView />
        </DataTemplate>

        <DataTemplate DataType="{x:Type vm:NewTabViewModel}">
            <v:NewTabView />
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding}">
                <ContentPresenter.Resources>

                    <!-- Header templates -->

                    <DataTemplate DataType="{x:Type vm:TabViewModel}">
                        <TextBlock Text="{Binding Name}"/>
                    </DataTemplate>

                    <DataTemplate DataType="{x:Type vm:NewTabViewModel}">
                        <TextBlock Text="+"/>
                    </DataTemplate>

                </ContentPresenter.Resources>
            </ContentPresenter>
        </DataTemplate>
    </TabControl.ItemTemplate>
</TabControl>
© www.soinside.com 2019 - 2024. All rights reserved.