C# 使用现成的WPF DataGrid显示预处理的动态数据

C# 使用现成的WPF DataGrid显示预处理的动态数据,c#,wpf,datagrid,system.reactive,dynamic-data,C#,Wpf,Datagrid,System.reactive,Dynamic Data,编辑2;关于这个问题的公认答案实际上并不适用于我。它可以编译并且看起来很好,但是它不像问题中的图片那样可视化数据(对我来说也是如此)。我看到一个包含分组对象的行的平面列表,而不是分组在一起的实际项目源的行。 答案没有明确提到DataGrid,而是ListView。这两个控件在每个集合中使用相同的CollectionView对象,因此ListView的适用对象也适用于DataGrid。 它也没有显示如何使用WPF控件完成绑定。要么这种方法在某一点上有效,但现在不再有效,要么从未有效过。 我的问题和

编辑2;关于这个问题的公认答案实际上并不适用于我。它可以编译并且看起来很好,但是它不像问题中的图片那样可视化数据(对我来说也是如此)。我看到一个包含分组对象的行的平面列表,而不是分组在一起的实际项目源的行。 答案没有明确提到DataGrid,而是ListView。这两个控件在每个集合中使用相同的CollectionView对象,因此ListView的适用对象也适用于DataGrid。 它也没有显示如何使用WPF控件完成绑定。要么这种方法在某一点上有效,但现在不再有效,要么从未有效过。 我的问题和链接的问题都是关于使用dynamicata进行过滤,人们通常使用ListCollectionView进行开箱即用的WPF过滤。无论是出于性能还是可用性方面的原因,使用默认的ListCollectionView展平项目并进行分组、排序和筛选都将无法达到目的。 这个问题可能已经成为一个XY问题,因为我的推理是WPF控件只理解ICollectionView,我有DynamicData数据,并且有一个适配器将这两个听起来都合乎逻辑

编辑1;要清楚;我说的是一种情况,在这种情况下,我最终得到了一组分组对象的变更集,例如
IObservable
,其中T是
ItemGroup:System.Linq.igroupping
。 问题在于正确地与数据网格控件通信,以确保项目源已经预先分组(也称为层次结构)。 我意识到提到预分类和预过滤可能会因为没有切中要害而造成混乱

我正在寻找一个演示,演示如何通过WPF Datagrid控件可视化来自DynamicData的预排序、过滤和分组数据。 我的意图是创建XAML代码,就像ItemsSource是ListCollectionView一样。数据将由绑定到可观察集合中的动态数据变更集操作符生成

我可以找到两个片段,它们暗示了将“开箱即用”WPF数据网格与DynamicCDATA相结合的可能性

两者都与实现正确的接口有关,因此WPF中的粘合代码可以处理其余部分。我对建议进行了测试,但没有成功;网格只是显示了我最外层的对象属性,例如ItemGroup.Key和ItemGroup.Count。我的期望是网格显示分组对象的记录,其中组容器由我的组样式模板定义。网格的作用就好像项目源是一个项目的平面列表(实际上是预先分组的)。 到目前为止,我理解了参考源代码,实际上并不支持它

第二次尝试是通过实现一个定制的CollectionView,它应该在DynamicData结果和数据网格控件之间进行代理。充其量我能制造一些视觉上的小故障;它也不起作用

我要么不够聪明,看不到明显的问题,要么与WPF控件集成很难。 请指导我如何解决这个问题,或者给我指出行为符合要求的代码

如果有必要,我不怕创建自己的粘合代码或扩展。也许WPF不适合这种类型的请求,在这种情况下,欢迎其他建议。
在本主题之前,我一直认为自己是一名技术娴熟的程序员,但这个障碍在我的脑海中留下了沉重的印象。

在WPF数据网格中显示预分组数据(例如:
IEnumerable
)最简单的方法就是使用数据模板在嵌套的数据网格中显示组内容

例如:

<Window x:Class="GroupingDisplay.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:GroupingDisplay"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <DataGrid ItemsSource="{Binding GroupingData}" HeadersVisibility="None" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding Key, Mode=OneWay}"/>
            </DataGrid.Columns>
            <DataGrid.RowDetailsTemplate>
                <DataTemplate>
                    <StackPanel>
                        <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
                            <DataGrid.Columns>
                                <DataGridTextColumn Binding="{Binding Data, Mode=OneWay}"/>
                            </DataGrid.Columns>
                        </DataGrid>
                    </StackPanel>
                </DataTemplate>
            </DataGrid.RowDetailsTemplate>
        </DataGrid>
    </Grid>
</Window>

以及背后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace GroupingDisplay
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public List<IGrouping<int, TestClass>> GroupingData { get; }
        public MainWindow()
        {
            InitializeComponent();

            var testData = new TestClass[]
            {
                new TestClass(1, "Horse"),
                new TestClass(1, "Cow"),
                new TestClass(2, "Bike"),
                new TestClass(2, "Car"),
                new TestClass(3, "House"),
                new TestClass(3, "Hotel")
            };

            GroupingData = testData
                .GroupBy(x => x.Key)
                .ToList();

            DataContext = this;
        }
    }

    public class TestClass
    {
        public int Key { get; }
        public string Data { get; }

        public TestClass(int key, string data)
        {
            Key = key;
            Data = data;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Data;
使用System.Windows.Documents;
使用System.Windows.Input;
使用System.Windows.Media;
使用System.Windows.Media.Imaging;
使用System.Windows.Navigation;
使用System.Windows.Shapes;
命名空间分组显示
{
/// 
///MainWindow.xaml的交互逻辑
/// 
公共部分类主窗口:窗口
{
公共列表分组数据{get;}
公共主窗口()
{
初始化组件();
var testData=newtestclass[]
{
新测试类(1,“马”),
新测试类(1,“Cow”),
新测试等级(2,“自行车”),
新测试等级(2,“汽车”),
新测试类(3,“房屋”),
新TestClass(3,“酒店”)
};
GroupingData=testData
.GroupBy(x=>x.Key)
.ToList();
DataContext=this;
}
}
公共类TestClass
{
公共int密钥{get;}
公共字符串数据{get;}
公共测试类(int键、字符串数据)
{
钥匙=钥匙;
数据=数据;
}
}
}
上面的简单类将显示3行,每组一行(1、2和3)。 然后,当您单击一行时,它将展开并显示该组的内容

如果要自动显示所有组内容,可以设置父数据网格的
RowDetailsVisibilityMode=“Visible”


DynamicATA支持从
SourceList
SourceCache
直接绑定到普通集合以进行显示。您只需调用myourcelist.Connect().Bind(myObservableCollection.Subscribe()在
源列表中进行更改<