使用ItemsSource时如何添加额外的项

11
在我正在构建的项目中,我有一个 TabControl,我想通过 ItemsSource 显示一系列选项卡。我还需要在 TabControl 的开头添加几个“概述”选项卡,这些选项卡不能位于 ItemsSource 中。
最好的方法是什么?我唯一能想到的方法是在我的 XAML 中添加概述选项卡,并通过代码手动添加选项卡,而不使用 ItemSource。这是最好的方法吗?
4个回答

18

您可以使用 CompositeCollection (MSDN) 来完成此操作:

<Window.Resources>
   <CollectionViewSource x:Key="ExistingTabs" Source="{Binding ExistingTabs}"/>
</Window.Resources>
<TabControl>
    <TabControl.ItemsSource>
        <CompositeCollection>
             <TabItem>SpecialItem</TabItem>
             <CollectionContainer Collection="{Binding Source={StaticResource ExistingTabs}}"/>
         </CompositeCollection>
    </TabControl.ItemsSource>
</TabControl>

你能解释一下为什么要使用 CollectionViewSource 而不是直接绑定到 ExistingTabs 吗?这是因为 CompositeCollection 没有继承 DataContext 或者会出现错误 Cannot find governing FrameworkElement 吗? - Brains
@Ghosthack 我老实说不记得为什么了,如果你尝试一下它能工作吗? - BradleyDotNET
是的,它有效了,CollectionViewSource 对此起了关键作用。不过,我只是想知道为什么。没问题,我会对 CollectionViewSource 进行更多研究。感谢您提供有用的答案。 - Brains

2

对于任何希望在 CollectionContainer 中使用 HeaderTemplate / ContentTemplate 的人:

首先,在 ViewModel 中添加 Type 属性。

public Type Type { get { return this.GetType(); } }

使用 Style.Triggers 来为由 Type 属性标识的动态选项卡设置 HeaderTemplate / ContentTemplate。
<Window x:Class="TabDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TabDemo"
        xmlns:vm="clr-namespace:TabDemo.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        d:DataContext="{d:DesignInstance vm:TabViewModel}">
    <Window.Resources>
        <CollectionViewSource x:Key="ExistingTabs" Source="{Binding ExistingTabs}"/>
        <DataTemplate x:Key="TemplateForTheHeader" DataType="{x:Type vm:TabViewModel}">
            <TextBlock Text="{Binding Title}"/>
        </DataTemplate>
        <DataTemplate x:Key="TemplateForTheContent" DataType="{x:Type vm:TabViewModel}">
            <DockPanel>
                <DataGrid ItemsSource="{Binding Data}"></DataGrid>
            </DockPanel>
        </DataTemplate>
        <Style x:Key="TabItemStyle" TargetType="TabItem">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Type}" Value="{x:Type vm:TabViewModel}">
                    <Setter Property="HeaderTemplate" Value="{StaticResource TemplateForTheHeader}" />
                    <Setter Property="ContentTemplate" Value="{StaticResource TemplateForTheContent}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    <Grid>
        <TabControl Grid.Row="1" ItemContainerStyle="{StaticResource TabItemStyle}">
            <TabControl.ItemsSource>
                <CompositeCollection>
                    <TabItem Header="Fixed Header">
                        <TabItem.Content>
                            <TextBlock Text="Fixed Content"/>
                        </TabItem.Content>
                    </TabItem>
                    <CollectionContainer Collection="{Binding Source={StaticResource ExistingTabs}}"/>
                </CompositeCollection>
            </TabControl.ItemsSource>
        </TabControl>
    </Grid>
</Window>

引用 Anderson Imes 的回答: https://dev59.com/DXM_5IYBdhLWcg3wgzdl#1348369

0
你可以使用CompositeCollection 如何在WPF中将泛型项添加到绑定到集合的ComboBox中
<TabControl>
        <TabControl.ItemsSource>
            <CompositeCollection>
                <TabItem Header="extra tab item"> //Not bound
                    <TextBox>something</TextBox>
                </TabItem>
                <CollectionContainer x:Name="cc"/>
            </CompositeCollection>
        </TabControl.ItemsSource>
    </TabControl>

代码实现:

cc.Collection=yourObservableCollection

-2

很遗憾,您不能将ItemsSource绑定与显式添加的Items集合对象混合使用。因此,您有两个选择,要么手动将固定项和绑定列表中的项添加到Items集合中,要么将ItemsSource绑定到一个包含一组固定对象和绑定集合项的集合中。在任何情况下,最大的问题可能是在数据更改时进行更新-确保正确的项被删除/添加并且UI正确更新。


2
-1 这不是真的。可以使用“CompositeCollection”来添加DataBound CollectionSources以及任意XAML定义的元素。 - Federico Berasategui
能否以答案的形式提供这个内容? - Hugoagogo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接