问题描述
编辑2;在链接的StackOverflow问题上接受的答案实际上对我不起作用。它可以编译并且看起来很好,但是它不能像问题中的图片一样可视化数据(再次对我而言)。我看到包含分组对象的行的平面列表,而不是实际项目源分组在一起的行。 答案没有明确提及DataGrid,而是提及ListView。这两个控件在每个集合中都使用相同的CollectionView对象,因此适用于ListView的对象也适用于DataGrid。 它还没有显示如何使用WPF控件完成绑定。这种方法要么在某一点上奏效了,要么不再奏效,或者从未奏效。 我的问题和链接的问题都是关于使用DynamicData进行过滤的,而该过滤通常是在现成的WPF中通常使用ListCollectionView进行的。展平项目并使用默认的ListCollectionView进行分组,排序和过滤将无法达到目的,无论是出于性能还是可用性方面的考虑。 这个问题可能已经成为XY问题,因为我的理由是WPF控件只能理解ICollectionView,我拥有DynamicData数据,而桥接两者的适配器听起来很合逻辑。
编辑1;要清楚;我说的是一种情况,最终我遇到了一组分组对象的变更集,例如IObservable<IChangeSet<T>>
,其中T是ItemGroup: System.Linq.IGrouping<TKey,TElement>
。
问题在于正确地与数据网格控件通信,即项目源已经预先分组(又称为分层)。
我意识到,提及预先排序和预先过滤的方法可能会引起混乱,因为这样做不切题。
我正在寻找有关如何通过WPF Datagrid控件可视化来自DynamicData的预排序,-筛选和-分组数据的演示。 我的意图是创建XAML代码,就像ItemsSource是ListCollectionView一样。数据将由绑定到可观察集合中的动态数据变更集运算符产生。
我可以找到两个片段,这暗示着将“开箱即用”的WPF数据网格与DynamicData结合的可能性;
- https://stackoverflow.com/a/52928955
- https://github.com/RolandPheasant/DynamicData.Snippets/blob/master/DynamicData.Snippets/Group/XamarinFormsGrouping.cs
两者都与实现正确的接口有关,因此WPF中的粘合代码可以处理其余的代码。我测试了这些建议,但无法使它起作用。网格只是显示了我最外层的对象属性,例如ItemGroup.Key和ItemGroup.Count。我的期望是网格显示分组对象的记录,其中由我的组样式模板定义了组容器。网格的作用就好像项目源是项目的平面列表(实际上是预先分组的)。 到目前为止,我已经了解了参考源,但实际上并不受支持。
通过实现自定义CollectionView进行了第二次尝试,该View应该在DynamicData结果和数据网格控件之间进行代理。充其量我可以产生一些视觉上的毛刺。它也不起作用。
我不够聪明,看不到明显的问题,或者很难与WPF控件集成。 请指导我如何解决此问题,或将我的代码指向符合要求的代码。
如有必要,我不怕创建自己的粘合代码或扩展名。也许WPF不适合这种类型的请求,在这种情况下,我们欢迎其他建议。 直到这个话题之前,我都认为自己是一个熟练的程序员,但是这个障碍在思想上让我很难受。
解决方法
在WPF DataGrid中显示预分组数据(例如:IEnumerable<IGrouping<TKey,TElement>>
)的最简单方法是简单地使用数据模板在嵌套DataGrid中显示组内容。
示例:
<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"),"Car"),new TestClass(3,"House"),"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;
}
}
}
上面的简单类将显示3行,每组一行(1、2和3)。 然后,当您单击一行时,它将展开并显示该组的内容。
如果要自动显示所有组内容,可以设置父级DataGrid的RowDetailsVisibilityMode="Visible"
。