【问题标题】:WPF : How to create separate Resources for each item in a bound ItemsControlWPF:如何为绑定 ItemsControl 中的每个项目创建单独的资源
【发布时间】:2026-01-06 15:35:01
【问题描述】:

我想实现以下目标:

  • 我的 ViewModel 公开了一个名为“Categories”的属性,它是 CategoryViewModel 对象的集合
  • 每个 CategoryViewModel 对象都公开了一个名为“Items”的属性,它是字符串的集合*。
  • 在我的视图中,我想要一个 TabControl,其中包含 'Categories' 集合中每个对象的 TabItem。
  • 每个 TabItem 的内容应该是一个 xceed DataGrid 控件,显示所选选项卡的 Items 集合的内容。

    <TabControl ItemsSource="{Binding Categories}">
        <TabControl.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding CategoryName}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <DataTemplate>
                <xcdg:DataGridControl
                        ItemsSource="{Binding Items}"
                        AutoCreateColumns="True">
                </xcdg:DataGridControl>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
    

当我直接绑定到 DataGridControl 的 ItemsSource 属性时,这可以正常工作。但是,为了利用 DataGridControl 的所有功能,我需要将 DataGridControl 的 ItemsSource 属性绑定到绑定到我的 Items 集合的 DataGridCollectionViewSource 对象。当网格没有嵌套在另一个控件中时,我会通过在 UserControl 的 Resources 部分中创建一个 DataGridCollectionViewSource 对象并绑定到该对象来执行此操作。

<UserControl>
    <UserControl.Resources>
        <xcdg:DataGridCollectionViewSource x:Key="GridData"
            Source="{Binding Items}" />
    </UserControl.Resources>
    <Grid>
        <xcdg:DataGridControl
                ItemsSource="{Binding Source={StaticResource GridData}}"
                AutoCreateColumns="True">
        </xcdg:DataGridControl>
    </Grid>
</UserControl>

我需要如何构造 XAML,以便在绑定 TabControl 时为每个 TabItem 创建一个 DataGridCollectionViewSource 对象,以便可以将在 TabItem 的内容中生成的 DataGridControl 绑定到它?

清如泥,对吧? :)

谢谢!

注意事项:

*在真正的解决方案中,集合包含一个比简单字符串更复杂的类的对象,但使用字符串使示例更简单。

【问题讨论】:

    标签: wpf xaml data-binding collections


    【解决方案1】:

    好的,这有点远,但你可以使用 DataGrid.Tag ...

    <TabControl.ContentTemplate>
        <DataTemplate>
            <xcdg:DataGridControl
                    ItemsSource="{Binding RelativeSource={RelativeSource Self}, Path=Tag}"
                    AutoCreateColumns="True">
                <xcdg:DataGridControl.Tag>
                     <xcdg:DataGridCollectionViewSource x:Key="GridData"
                          Source="{Binding Items}" />
                </xcdg:DataGridControl.Tag>
            </xcdg:DataGridControl>
        </DataTemplate>
    </TabControl.ContentTemplate>
    

    或者...资源可以在任何FrameworkElement上定义,所以你可以尝试:

    <TabControl.ContentTemplate>
        <DataTemplate>
            <xcdg:DataGridControl
                    ItemsSource="{Binding Source={StaticResource GridData}}"
                    AutoCreateColumns="True">
                <xcdg:DataGridControl.Resources>
                     <xcdg:DataGridCollectionViewSource x:Key="GridData"
                          Source="{Binding Items}" />
                </xcdg:DataGridControl.Resources>
            </xcdg:DataGridControl>
        </DataTemplate>
    </TabControl.ContentTemplate>
    

    我不使用 eXceed Grid,因此无法测试这些是否有效 - 只需尝试几个想法!

    科林 E.

    【讨论】:

    • E:感谢您的尝试。我尝试了您的两个建议,但都无法正常工作。你的第二个建议与我通过 decyclone 对 x:Shared 的建议所尝试的很接近。 (如果可以的话,我会给你代表建议)
    • 没问题 - 现在完全没有想法了 :-(
    【解决方案2】:

    您可以在资源上使用x:Shared="True" 属性。这意味着每次使用该资源都会创建一个新实例。

    示例:

    <UserControl.Resources>
        <xcdg:DataGridCollectionViewSource x:Key="GridData" 
            x:Shared="False"
            Source="{Binding Items}" />
    </UserControl.Resources>
    

    【讨论】:

    • 谢谢。我认为这是朝着正确方向迈出的一步。我将 DataGridCollectionViewSource 的声明移到 DataTemplate 的 Resources 属性中,因为这对我来说似乎更有意义。 (因为每个 DataGridControl 都需要它自己的 DataGridCollectionViewSource 类实例,但每个实例都需要绑定到不同的集合。)
    • 这样编译运行没有错误,但是没有达到预期的效果。我的网格中没有数据。另外,我很好奇为什么 x:Shared 选项没有出现在智能感知中……很奇怪。
    • @BigFunger:我的错。它实际上应该是x:Shared="False"。我们不想分享它,对吧?