我想使用LINQ
在内存数据表中查询并在DataGridView
上查看结果
有些时候我想重用这段代码(LINQ
),然后我不能将列名硬编码为。因为有些时候列大小可能不同,所以我想为每个搜索条件逐一编写LINQ码。
var filter = (from myrow in rsTable.AsEnumerable()
orderby myrow[0]
where myrow.Field<string>(0).ToLower().Contains(search) || myrow.Field<string>(1).ToLower().Contains(search)
select myrow).ToList().CopyToDataTable();
如果有一种方法可以将参数作为列名称或任何方法传递,以将此部分作为函数或该部件的任何解决方案进行改进?
示例代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace SampleLambdaExp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
dataGridView1.DataSource = GetDataTable();
}
private DataTable GetDataTable() {
string str = Properties.Settings.Default.Setting;
SqlConnection con = new SqlConnection();
con.ConnectionString = str;
string query = "SELECT [Description] ,[Type] ,[Category] FROM [AdventureWorks2008R2].[Sales].[SpecialOffer]";
con.Open();
SqlCommand com = new SqlCommand(query,con);
SqlDataAdapter da = new SqlDataAdapter(com);
DataSet ds = new DataSet();
da.Fill(ds);
return ds.Tables[0];
}
private void DetailsFilter(string search)
{
dataGridView1.DataSource = null;
DataTable rsTable = null;
rsTable = GetDataTable();
try
{
var filter = (from myrow in rsTable.AsEnumerable()
orderby myrow[0]
where myrow.Field<string>(0).ToLower().Contains(search) || myrow.Field<string>(1).ToLower().Contains(search)
select myrow).ToList().CopyToDataTable();
if (filter.Rows.Count > 0)
{
dataGridView1.DataSource = filter;
dataGridView1.Columns[0].Visible = false;
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "" || textBox1.Text == String.Empty) { dataGridView1.DataSource = GetDataTable(); }
else
{
DetailsFilter(textBox1.Text.ToLower());
}
}
}
}
这是Windows窗体
答案 0 :(得分:1)
最简单的方法是停止使用LINQ查询DataTable
并开始使用DataView
(并设置其RowFilter
property)。
然后只需将DataView
绑定到您的DataGridView
即可。这也有一个好处,即每当过滤条件发生变化时,您都不需要创建一个全新的DataTable
。
所以你的代码看起来像:
public partial class Form1 : Form
{
readonly DataTable _data;
public Form1()
{
InitializeComponent();
// querying a database in a ctor is bad IMHO, but that's just example code
// keep a reference to the data once loaded
_data = GetDataTable();
// bind the gridview to the default DataView instead of the DataTable
dataGridView1.DataSource = _data.DefaultView;
}
private DataTable GetDataTable() {
...
}
private void DetailsFilter(string search, IEnumerable<string> columnNames)
{
// create the filter with AND and LIKE
var filterString = String.Join(" AND ", columnNames.Select(c => String.Format("{0} LIKE '%{1}%'", c, search)));
_data.DefaultView.RowFilter = filterString;
// since the grid is bound the DataView, you immediately see the result
}
private void button1_Click(object sender, EventArgs e)
{
if (textBox1.Text == "" || textBox1.Text == String.Empty)
{
_data.DefaultView.RowFilter = String.Emtpy;
}
else
{
// note how we can pass column names
DetailsFilter(textBox1.Text.ToLower(), new []{"Description", "Category"});
}
}
}
请注意它的缩短程度,避免多次查询数据库。
至于排序,只需Sort
property。