简体   繁体   English

LINQ:动态Where子句,用于切换案例组合

[英]LINQ: dynamic Where clause with toggle the combination of cases

I have a list binded to angridview and i want to be able to create filter Where clause 'on the fly', while the combination of filter option controlled by user. 我有一个绑定到angridview的列表,我希望能够“动态”创建过滤器Where子句,同时由用户控制过滤器选项的组合。

What is the best way to filter the original list by model boolean property and allow to toggle every condition of filter? 按模型布尔属性过滤原始列表的最佳方法是什么,并允许切换过滤器的每个条件?

I know that the filterdList is not nececery, but every other solution i've already saw doesn't allow toggle the condition of Where clause. 我知道filterdList不是nececery,但我已经看过的其他解决方案都不允许切换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();
    }

}

模拟

Try something like this (untested): 尝试这样的事情(未经测试):

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

}

There are other ways you could reduce duplication, but this is a start. 还有其他方法可以减少重复,但这是一个开始。

I would say that the easiest/cleanest way is using ADO.NET DataSet for handling your data instead of a using a bunch of List with some Linq query. 我想说最简单/最干净的方法是使用ADO.NET DataSet来处理你的数据,而不是使用一堆带有一些Linq查询的List。 ADO.NET DataSet is the Official Winforms Way of life . ADO.NET DataSet是官方的Winforms生活方式

You could use these dataset/datatable with a BindingSource component as the DataSource of your DataGridView and use the Filter String Property of the BindingSource. 您可以将这些数据集/数据表与BindingSource组件一起用作DataGridView的DataSource,并使用BindingSource的Filter String属性。 This String expression could be easily build by some If clauses testing the state of your CheckBox and String concatenation following the MSND DataColumn Expression syntax. 这个String表达式可以通过一些If子句轻松构建,这些子句按照MSND DataColumn表达式语法测试CheckBox的状态和字符串连接。

There are some other clean way like extending the BindingList class with a partial implementation of the IBindingListView interface. 还有一些其他干净的方法,比如使用IBindingListView接口的部分实现来扩展BindingList类。 But that's some pretty hard stuff, specially when you know that Microsoft has done this work for you for the DataSet... This article is a good place to start if you are not afraid. 但这是一些相当困难的东西,特别是当你知道微软已经为你为DataSet做了这项工作时...如果你不害怕,这篇文章是一个很好的起点。

a single event handler can be reused for every CheckBox, and that event handler can compare every property with respective CheckBox. 可以为每个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();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM