C# 按一系列属性对BindingSource进行排序,BindingSource是一组对象

C# 按一系列属性对BindingSource进行排序,BindingSource是一组对象,c#,winforms,entity-framework,sorting,datagridview,C#,Winforms,Entity Framework,Sorting,Datagridview,这个问题已经被问了很多次(我知道),但是我无法实现一些特别适合我的东西 我使用实体框架来处理与WinForms应用程序的数据交互(对contept来说有些陌生);这很好,意味着任何DataGridView控件的DataSource都是一个对象列表 用户将能够对多个列进行排序。对于没有数据源的DataGridView控件(因为它们是单向的,并且我直接从数据库中提取了数据),这不是问题,因为自定义IComparer类处理此排序 但是,我似乎无法对具有DataSource的网格进行排序,其中DataS

这个问题已经被问了很多次(我知道),但是我无法实现一些特别适合我的东西

我使用实体框架来处理与WinForms应用程序的数据交互(对contept来说有些陌生);这很好,意味着任何DataGridView控件的
DataSource
都是一个对象列表

用户将能够对多个列进行排序。对于没有
数据源的DataGridView控件
(因为它们是单向的,并且我直接从数据库中提取了数据),这不是问题,因为自定义
IComparer
类处理此排序

但是,我似乎无法对具有
DataSource
的网格进行排序,其中
DataSource
是由多个列组成的一组对象

需要注意的重要一点是,DataGridView的
数据源
可以是任何类型(客户、食谱、汽车等)的对象列表,因为网格可以通过对象表示数据库中任何表中的数据

我获取DataGridView控件的
数据源的方法如下(此示例适用于系统中的用户):

当DataGridView的
DataSource
是一个直接的数据库查询
DataTable
时,我可以简单地将DataGridView的
DataSource
转换为
BindingSource
,然后将
Sort
属性设置为排序字符串。例如,如果先按用户名再按配置文件对用户列表进行排序,则排序如下:

((BindingSource)DataSource).Sort = SortArgs;
其中SortArgs=“用户名ASC,配置文件ASC”。这可以通过迭代已排序的列并提取和连接列的
DataPropertyName
来确定

但是,如果我尝试强制转换DataGridView控件的
数据源
,该控件绑定到上述
用户列表
对象集,则会出现编译时错误,表明无法执行强制转换

为了尝试解决这个问题,我从现有的
数据源创建了一个新的
BindingSource
,然后尝试应用相同的排序逻辑(只创建排序字符串,然后将其传递给
BindingSource
sort
属性):

不幸的是,当我这样做时,
SupportsAdvancedSorting
属性总是
false
,尽管
BindingSource
实现了
IBindingListView
,这篇文章对此属性进行了说明


我主要想理解的是,为什么这个属性总是被设置为
false
,尽管我使用的类实现了允许多列排序的必需接口。我还看到了一些关于如何实现按多个属性对对象列表进行排序的示例,例如,除非我理解错误,否则这仍然依赖于强类型的IList输入。

作为一个选项,您可以向项目添加
System.Linq.Dynamic
引用,然后,在使用
System.Linq.Dynamic
名称空间后,您将能够通过传递排序列和排序顺序作为
string
,对
IEnumerable
IQueryable
进行排序,例如:

var list = db.Products.ToList();
bindingSource1.DataSource = list.OrderBy("Name ASC, Price DESC").ToList();
资源

  • 对于
    System.Linq.Dynamic
    。您只需在软件包管理器控制台中使用以下命令即可安装软件包:
    install package System.Linq.Dynamic

  • 对于
    System.Linq.Dynamic

  • 关于动态LINQ(第1部分:使用LINQ动态查询库)


有什么问题或想法吗?有什么问题或成功吗?:)再次感谢您的投入。系统Linq.Dynamic对于从数据库进行初始加载非常有用,但是我要处理的另一方面是有一个BindingSource,其数据源包含一组实体,例如销售订单或客户。如果在代码中,我声明了一个强类型列表,其中T:我知道的类型在数据源中,那么我可以加载到一个列表中并使用动态LINQ。但是,如果我尝试将其声明为List,它会说它找不到我正在排序的字段,尽管调试器中的两个列表相同。为什么要使用
List
?如果您知道
BindingSource
DataSource
中的对象实际上是一个
列表
,那么使用
var data=bindingSource1.SataSource作为列表就足够了。我在Windows窗体、WCF、Web Api和ASP.NET MVC中使用了
System.Linq.Dynamic
来实现这一目的(如您的要求),没有任何问题。因此,如果你在应用解决方案时有任何问题,请告诉我。啊,也许我解释得不够好;我不知道在当时它是一个
列表
、一个
列表
还是一个
列表
;我只知道它可能是其中任何一个的列表。我目前正在研究反射如何通过以这种方式确定类型,然后以某种方式实例化相应类型的“列表”来实现这一点;它最终只是一行:
(数据源作为BindingSource)。数据源=((数据源作为BindingSource)。列表作为IEnumerable)。OrderBy(SortArgs)
BindingSource GridBindingSource = new BindingSource(DataSource, null);
SortedGridBinding.Sort = SortArgs;
var list = db.Products.ToList();
bindingSource1.DataSource = list.OrderBy("Name ASC, Price DESC").ToList();