【问题标题】:Add extra items when using ItemsSource使用 ItemsSource 时添加额外的项目
【发布时间】:2014-07-09 09:59:31
【问题描述】:

在我正在构建的项目中,我有一个TabControl,我想通过ItemsSource 在其中显示一系列选项卡。我还需要在TabControl 的开头有一些“概述”选项卡,它们不能位于ItemsSource 中。

实现这一点的最佳方法是什么,我能想到的唯一方法是在我的 XAML 中添加概览选项卡,并通过代码手动添加选项卡项而不是使用 ItemSource 这是最好的方法关于它。

【问题讨论】:

    标签: c# wpf tabcontrol


    【解决方案1】:

    您可以使用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还是出现找不到管理FrameworkElement的错误?
    • @Ghosthack 老实说,我不记得为什么了,如果你尝试一下,它会起作用吗?
    • 是的,它有效,CollectionViewSource 是它的关键。但是,我只是对为什么感兴趣。没问题,我会做更多关于CollectionViewSource 的研究。感谢您提供有用的答案。
    【解决方案2】:

    对于任何找到将 HeaderTemplate / ContentTemplate 与 CollectionContainer 一起使用的方法的人:

    首先在 ViewModel 中添加类型属性

    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://stackoverflow.com/a/1348369/1196637

    【讨论】:

      【解决方案3】:

      您可以使用 CompositeCollection How do you add a generic item to a ComboBox bound to a collection in WPF

      <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
      

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • -1 这不是真的。有一个 CompositeCollection 可用于添加 DataBound CollectionSources 以及任意 XAML 定义的元素。
        • 愿意提供这个作为答案吗?
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-11-12
        • 2017-01-25
        • 2021-12-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多