【问题标题】:LINQ: dynamic Where clause with toggle the combination of casesLINQ:带有切换案例组合的动态 Where 子句
【发布时间】:2018-11-01 03:55:42
【问题描述】:

我有一个绑定到 angridview 的列表,我希望能够“即时”创建过滤器 Where 子句, 而过滤选项的组合由用户控制。

通过模型布尔属性过滤原始列表并允许切换过滤器的每个条件的最佳方法是什么?

我知道 filterdList 不是必需的,但我已经看到的所有其他解决方案都不允许切换 Where 子句的条件。

public partial class Form1 : Form
{
    List<dummy> Origlist = new List<dummy> {
        new dummy { pk = 1 ,  istype1 = true,  istype2  = false, istype3=false, istype4=false },
        new dummy { pk = 2 ,  istype1 = true,  istype2 = false,  istype3=false, istype4=false },
        new dummy { pk = 3 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 4 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 5 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 6 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 7 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true },
        new dummy { pk = 8 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true },
        new dummy { pk = 9 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 10 , istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 11 , istype1 = false, istype2 = false,  istype3=false, istype4=false }
        };
    List<dummy> filteredList = new List<dummy>(); 
    public Form1()
    {
        InitializeComponent();
    }

    private void Bind()
    {
        dataGridView1.DataSource = null;
        dataGridView1.DataSource = filteredList;
    }


    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox1.Checked)
        {
            filteredList.AddRange(Origlist.Where(a => a.istype1 == true).ToList());
        }
        else
        {
            filteredList.RemoveAll(a => a.istype1 == true);
        }
        Bind();
    }



    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox2.Checked)
        {
            filteredList.AddRange(Origlist.Where(a => a.istype2 == true).ToList());
        }
        else
        {
            filteredList.RemoveAll(a => a.istype2 == true);
        }
        Bind();
    }

    private void checkBox3_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox3.Checked)
        {
            filteredList.AddRange(Origlist.Where(a => a.istype3 == true).ToList());
        }
        else
        {
            filteredList.RemoveAll(a => a.istype3 == true);
        }
        Bind();
    }

    private void checkBox4_CheckedChanged(object sender, EventArgs e)
    {
        if (checkBox4.Checked)
        {
            filteredList.AddRange(Origlist.Where(a => a.istype4 == true).ToList());
        }
        else
        {
            filteredList.RemoveAll(a => a.istype4 == true);
        }
        Bind();
    }

}

【问题讨论】:

标签: c# winforms linq filter


【解决方案1】:

试试这样的东西(未经测试):

public partial class Form1 : Form
{
    List<dummy> Origlist = new List<dummy> {
        new dummy { pk = 1 ,  istype1 = true,  istype2  = false, istype3=false, istype4=false },
        new dummy { pk = 2 ,  istype1 = true,  istype2 = false,  istype3=false, istype4=false },
        new dummy { pk = 3 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 4 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 5 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 6 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 7 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true },
        new dummy { pk = 8 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true },
        new dummy { pk = 9 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
        new dummy { pk = 10 , istype1 = false, istype2 = true,   istype3=false, istype4=false },
        new dummy { pk = 11 , istype1 = false, istype2 = false,  istype3=false, istype4=false }
    };

    Options options = new Options();

    private class Options {
        public bool istype1 { get; set; }
        public bool istype2 { get; set; }
        public bool istype3 { get; set; }
        public bool istype4 { get; set; }
    }

    public Form1()
    {
        InitializeComponent();
    }

    private void Bind()
    {
        dataGridView1.DataSource = null;
        dataGridView1.DataSource = OrigList.Where(a =>
          (options.istype1 && a.istype1) ||
          (options.istype2 && a.istype2) ||
          (options.istype3 && a.istype3) ||
          (options.istype4 && a.istype4)
        ).ToList();
    }


    private void checkBox1_CheckedChanged(object sender, EventArgs e)
    {
        options.istype1 = checkBox1.checked;
        Bind();
    }



    private void checkBox2_CheckedChanged(object sender, EventArgs e)
    {
        options.istype2 = checkBox2.checked;
        Bind();
    }

    private void checkBox3_CheckedChanged(object sender, EventArgs e)
    {
        options.istype3 = checkBox3.checked;
        Bind();
    }

    private void checkBox4_CheckedChanged(object sender, EventArgs e)
    {
        options.istype4 = checkBox4.checked;
        Bind();
    }

}

还有其他方法可以减少重复,但这是一个开始。

【讨论】:

    【解决方案2】:

    我想说最简单/最干净的方法是使用 ADO.NET DataSet 来处理您的数据,而不是使用一堆带有一些 Linq 查询的 List。 ADO.NET DataSet 是 Winforms 的官方生活方式

    您可以将这些数据集/数据表与 BindingSource 组件一起用作 DataGridView 的 DataSource,并使用 BindingSource 的 Filter String 属性。这个 String 表达式可以很容易地通过一些 If 子句按照MSND DataColumn Expression 语法测试 CheckBox 和 String 连接的状态来构建。

    还有其他一些干净的方法,例如使用 IBindingListView 接口的部分实现来扩展 BindingList 类。但这是一些相当困难的事情,特别是当您知道 Microsoft 已经为您完成了 DataSet 的这项工作时...如果您不害怕,这个article 是一个很好的起点。

    【讨论】:

      【解决方案3】:

      可以为每个 CheckBox 重复使用单个事件处理程序,并且该事件处理程序可以将每个属性与相应的 CheckBox 进行比较。

      List<dummy> Origlist = new List<dummy> 
      {
          new dummy { pk = 1 ,  istype1 = true,  istype2 = false,  istype3=false, istype4=false },
          new dummy { pk = 2 ,  istype1 = true,  istype2 = false,  istype3=false, istype4=false },
          new dummy { pk = 3 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
          new dummy { pk = 4 ,  istype1 = false, istype2 = true,   istype3=false, istype4=false },
          new dummy { pk = 5 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
          new dummy { pk = 6 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
          new dummy { pk = 7 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true  },
          new dummy { pk = 8 ,  istype1 = false, istype2 = false,  istype3=false, istype4=true  },
          new dummy { pk = 9 ,  istype1 = false, istype2 = false,  istype3=true,  istype4=false },
          new dummy { pk = 10 , istype1 = false, istype2 = true,   istype3=false, istype4=false },
          new dummy { pk = 11 , istype1 = false, istype2 = false,  istype3=false, istype4=false }
      };
      
      public Form1()
      {
          InitializeComponent();
      }
      
      private void checkBox_CheckedChanged(object sender, EventArgs e)
      {
           dataGridView1.DataSource = Origlist.Where(a => 
               a.istype1 == checkBox1.Checked && 
               a.istype2 == checkBox2.Checked && 
               a.istype3 == checkBox3.Checked && 
               a.istype4 == checkBox4.Checked).ToList();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多