【问题标题】:How to replace OrderBy from linq.dynamic with OrderBy from regular linq?如何用来自常规 linq 的 OrderBy 替换来自 linq.dynamic 的 OrderBy?
【发布时间】:2020-05-27 15:41:05
【问题描述】:

为了简单起见,我有一个数据库表记事本,它有两列(id、文本)。我在 DataGridView 中显示我的查询结果。我想要做的是当用户点击任一标题时,数据将根据标题文本进行排序。

我能够使用 Linq.Dynamic OrderBy 实现这一点,如下所示。

  private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  {
     if (sortAscending)
     {
        notepadDataGridView.DataSource = notes.OrderBy(notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName).ToList();
        notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
     }
     else
     {
        notepadDataGridView.DataSource = notes.OrderBy(notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName).Reverse().ToList();
        notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
     }

     sortAscending = !sortAscending;
  }

我想用 System.Linq 中的常规 OrderBy 替换它。问题是这个函数需要一个 lambda 表达式,如果像这样使用它会使代码很长,如果我们有 20 列要排序,它就无法维护。

  private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  {
     if (sortAscending)
     {
        if (notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName == "id")
        {
           notepadDataGridView.DataSource = notes.OrderBy(note => note.Id).ToList();
           notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
        }
        else if (notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName == "text")
        {
           notepadDataGridView.DataSource = notes.OrderBy(note => note.Text).ToList();
           notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
        }


     }
     else
     {
        //Sort descending
     }

     sortAscending = !sortAscending;
  }

感谢任何反馈

//编辑

//这将查询数据库表注 List<Note> notes = nodteLogic.GetNotes();

Note 对象有两个属性 Id 和 Text 那么我要做的就是以下

notepadBindingSource.DataSource = notes;
notepadDataGridView.DataSource = notepadBindingSource;

dataGrid 将填充列表值

【问题讨论】:

  • 当您单击列标题时,DataGridView 不是完全在执行此操作吗(除非您设置了Column.SortMode = NotSortable)?然后,如果您需要手动对数据进行排序,可以使用DataTable.DefaultView.Sort 属性。您是否有理由尝试使用执行相同操作的自定义行为来覆盖默认行为?
  • 我没有将列显式添加到 dataGrid,我根据节点列表的内容添加列,因此,我无法设置 Column.SortMode
  • 你不需要设置它。默认值为Automatic。什么是节点列表?你没有有一个数据库表记事本吗?您的意思是您已将数据从数据库加载到不可排序的List<OfSomething>?您能否为问题提供更多背景信息并更好地描述您正在使用的对象?
  • “常规”linq 的 OrderBy 需要 Func<T, TKey>,没有非通用版本。这意味着即使您制作了一个 lambda 生成器 static Func<Note, T> GenerateLambda<T>(string property_name)(这很容易做到),您也必须将其称为 OrderBy(GenerateLambda<int>("int_property"))OrderBy(GenerateLambda<string>("string_property")),这再次需要手动切换,这次是在类型上属性(intstring),而不是名称。

标签: c# winforms linq


【解决方案1】:

我可以像这样使用常规的 linq,谢谢大家的帮助。

  private void dataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e)
  {

     if (sortAscending)
     {
        notepadDataGridView.DataSource = notes.OrderBy(note => note.GetType().GetProperty(notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName)
                                                        .GetValue(note, null)).ToList();
        notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
     }
     else
     {
        notepadDataGridView.DataSource = notes.OrderBy(note => note.GetType().GetProperty(notepadDataGridView.Columns[e.ColumnIndex].DataPropertyName)
                                                        .GetValue(note, null)).Reverse().ToList();
        notepadDataGridView.Columns[e.ColumnIndex].HeaderCell.SortGlyphDirection = SortOrder.Descending;
     }

     sortAscending = !sortAscending;
  }

【讨论】:

    【解决方案2】:

    如果您想处理 DataGridView 的内容,最好将内容与其显示方式分开。在 WPF 中这是标准的,在 WinForms 中鼓励使用 BindingList<T>

    创建一个可排序的NotesBindingList并不难,派生自BindingList<Note>。您必须启用排序,并覆盖排序方法。

    如果你使用 Nuget 包Equin.ApplicationFramework.BindingListView 会更容易。

    此 BindingListView 通过单击列标题以正确的方向为您提供自动排序。

    List<Note> notes = GetNotes();
    BindingListView<Note> viewNotes = new BindingListView<Note>(notes);
    this.dataGridView1.DataSource = viewNotes;
    

    这足以显示您的笔记。如果单击列的标题,注释将使用默认的 IComparer 以正确的顺序排序。列标题中的字形会自动更新。

    如果你想要一个非标准的排序顺序,你必须提供一个 IComparer 并调用ApplySort(IComparer&lt;T&gt; comparer);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-21
      • 2019-01-12
      • 2020-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多