代码之家  ›  专栏  ›  技术社区  ›  shdr

LINQ:动态WHERE子句,用于切换事例组合

  •  2
  • shdr  · 技术社区  · 6 年前

    我有一个绑定到angridview的列表,我希望能够创建filter-where子句'on-fly', 同时过滤选项的组合由用户控制。

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

    我知道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();
        }
    
    }
    

    simulation

    3 回复  |  直到 6 年前
        1
  •  3
  •   Evan Trimboli    6 年前

    尝试类似的操作(未测试):

    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
  •  3
  •   Marco Guignard    6 年前

    我想说,最简单/最干净的方法是使用ADO.NET数据集来处理数据,而不是使用一组列表和一些LINQ查询。ADO.NET数据集是 官方的Winforms生活方式 .

    您可以使用这些数据集/数据表和bindingSource组件作为DataGridView的数据源,并使用bindingSource的筛选字符串属性。这个字符串表达式可以很容易地由一些if子句构建,这些子句测试复选框的状态以及后面的字符串连接 MSND DataColumn Expression 语法。

    还有其他一些干净的方法,比如使用IBindingListView接口的部分实现扩展bindingList类。但这是相当困难的事情,特别是当你知道微软已经为你做了数据集的这项工作时…这个 article 如果你不害怕的话,是一个很好的开始的地方。

        3
  •  1
  •   ASh aminescm    6 年前

    可以为每个复选框重用单个事件处理程序,并且该事件处理程序可以将每个属性与各自的复选框进行比较。

    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();
    }