从C#中的实体填充的数据中过滤Datagrid View [英] Filter Datagrid View from data populated from entity in C#

查看:46
本文介绍了从C#中的实体填充的数据中过滤Datagrid View的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C#的新手,可能这可能是重复的,但无法对datagrid视图上的记录进行过滤,而datagrid视图的列是根据TextBox change事件的设计器视图设计的.

这是我的代码,用于填充datagridview.任何帮助将不胜感激.

  IList< ProductEntity>emp = HibernateDao.fetchDAta();IList< ProductModel>产品=新列表< ProductModel>();foreach(emp中的ProductEntity e){dataGridView1.Rows.Add(" + e.id,e.barcode,e.product_name,e.product_desc,e.quantity +" + e.units," + e.buying_price,e.retail_selling_price,e.can_sell_whole_sale,e.whole_selling_price);} 

这是试图进行过滤的代码,根本无法正常工作

  BindingSource bs = new BindingSource();私有void metroTextBox1_TextChanged(对象发送者,EventArgs e){如果(metroTextBox1.Text == string.Empty){bs.RemoveFilter();}别的{bs.Filter = string.Format("product_name LIKE'* {0} *'",metroTextBox1.Text);}} 

和是我需要过滤的,由设计师设计的datagrid视图

解决方案

考虑以下类似内容:

  IList< ProductEntity>emp = HibernateDao.fetchDAta();//似乎没有操作,您是否错过了映射通话?:IList< ProductModel>产品=新列表< ProductModel>();BindingSource bs = new BindingSource();bs.DataSource = emp;//emp必须是一个可绑定的列表;fetchData做ToList()吗?bs.Filter ="[product_name] ='cornflakes'";dataGridView1.Columns.Clear();dataGridView1.AutoGenerateColumns = true;dataGridView1.DataSource = bs; 

您无法使DataGridView在单个列中显示两个属性,因此 e.quantity +""+ e.units 类型的内容将无法解决.您必须向ProductModel添加一个属性(而非字段),该属性将这两个值作为单个字符串返回

数据绑定并不是一件复杂的事情.从某种意义上说,您已经在做其中的一部分.这个循环让您迭代数据模型并将所有内容填充到网格中-数据绑定将为您做到这一点,如果您只是将网格的数据源设置为支持绑定的列表,则网格将为每个列表项创建一行(并且在autogeneratecolumns模式下,它将为找到的每个简单属性生成一列).绑定的另一个技巧是,当您更改模型时(应该通过更改模型而不是通过编程方式更改网格单元来更改数据),网格会更新以反映更改.

它有助于实现模型/视图/控制器表示的关注点分离


如果 HibernateDao.fetchDAta()返回的内容未实现IBindingListView接口,您可以考虑:

  1. 要安装nuget软件包 morelinq ;它具有将对象列表转换为数据表的方法,并且数据表完全支持过滤或

  2. 安装nuget软件包 System.Linq.Dynamic ;它可以让您通过编写字符串表达式来使用linq查询事物

新建一个项目,并用此演示完全替换Form1.vb的内容:

 导入System.Linq.Dynamic进口更多公开课表格1班级人士属性名称作为字符串财产年龄整数末级私有dgvDL作为新的DataGridView私有dgvBLV作为新的DataGridView私人TB作为新的文本框私人名单(人名)私有子Form1_Load(作为对象发送,作为EventArgs发送)处理MyBase.Load昏暗的名字()= {约翰",詹姆斯"}people = names.Select(Function(x)New Person with {.Name = x,.Age = x.Length * 7}).ToList()'动态linq dgvdgvDL.DataSource =人员Me.Controls.Add(dgvDL)'morelinq DGVDim bs作为新的BindingSourcebs.DataSource = people.ToDataTable()dgvBLV.DataSource = bsMe.Controls.Add(dgvBLV)'不相关的用户界面代码AddHandler tb.TextChanged,AddressOf TextChangeMe.Controls.Add(tb)dgvBLV.Location =新点(dgvDL.Right,dgvDL.Top)'与上方网格相邻的位置tb.Location =新点(dgvDL.Left,dgvDL.Height)结束子私有子TextChange(发送者作为对象,e作为EventArgs)如果(tb.Text ="),则dgvDL.DataSource =人员过滤DL网格DirectCast(dgvBLV.DataSource,BindingSource).RemoveFilter()'过滤BLV网格别的dgvDL.DataSource = people.Where("Name == @ 0&",tb.Text).ToList()'过滤DL网格DirectCast(dgvBLV.DataSource,BindingSource).Filter = $" [名称] ='{tb.Text}'"'过滤器BLV网格万一结束子末级 

注意,如果您准备使用不使用内置字符串过滤器的LINQ进行过滤,则不需要这些帮助程序库中的任何一个;您可以只使用普通的LINQ-在 TextChange 方法中看到我说的 .Where(" Name == @ 0" ;, tb.Text)-因为 Name在这里是硬编码的,也可以很容易地在 .Where(Function(x)x.Name = tb.Text)处进行编码.如果也要构造左侧,动态LINQ只会真正使您的生活更轻松

-

编辑

C#版本,与VB的差别不大.不知道为什么我的大脑会滑入VB.NET,但是我已经将上面的VB留给您与之进行比较,以作为这就是读取VB的方式".几个关键字和分号,知道如何阅读其他形式的.NET总是很方便的:

 使用System.Linq.Dynamic;使用System.Data;使用System.Drawing;使用System.Linq;使用System.Windows.Forms;使用系统;使用System.Collections.Generic;使用MoreLinq;命名空间WindowsFormsApp1{公共局部类Form1:表单{公共Form1(){base.Load + = Form1_Load;}公共偏见类人{公共字符串名称{get;放;}public int年龄{get;放;}}私有DataGridView dgvDL = new DataGridView();私有DataGridView dgvBLV =新DataGridView();私人TextBox tb = new TextBox();私人名单<人>人们;私有void Form1_Load(对象发送者,EventArgs e){var names = new string [] {"John","James"};人员=名称.选择(x => new Person(){名称= x,年龄= x.Length * 7}).ToList();//动态linq dgvdgvDL.DataSource =人员;this.Controls.Add(dgvDL);//morelinq DGVvar bs = new BindingSource();bs.DataSource = people.ToDataTable();dgvBLV.DataSource = bs;this.Controls.Add(dgvBLV);//不相关的UI代码this.tb.TextChanged + = TextChange;this.Controls.Add(tb);dgvBLV.Location =新点(dgvDL.Right,dgvDL.Top);//与上方网格相邻tb.Location = new Point(dgvDL.Left,dgvDL.Height);}私有无效TextChange(对象发送者,EventArgs e){如果(tb.Text =="){dgvDL.DataSource =人员;//过滤DL网格((BindingSource)dgvBLV.DataSource).RemoveFilter();//过滤BLV网格}别的{dgvDL.DataSource = people.Where("Name == @ 0&",tb.Text).ToList();//过滤DL网格((BindingSource)dgvBLV.DataSource).Filter = $" [名称] ='{tb.Text}'';}//过滤BLV网格}}} 

I am newbie in C# and probably this might be a possible duplicate but am unable to do filter of records on datagrid view whose columns were designed from designer view on TextBox change event.

This is my code to populate the datagridview. Any help will be highly appreciated.

IList<ProductEntity> emp = HibernateDao.fetchDAta();

IList<ProductModel> products = new List<ProductModel>();

foreach(ProductEntity e in emp)
{
    dataGridView1.Rows.Add("" + e.id, e.barcode, e.product_name, e.product_desc, e.quantity + " " + e.units,""+e.buying_price,e.retail_selling_price,e.can_sell_whole_sale,e.whole_selling_price);
}

And this is the code that have tried to do filter which is not working at all

BindingSource bs=new BindingSource();

private void metroTextBox1_TextChanged(object sender, EventArgs e)
{


   if (metroTextBox1.Text == string.Empty)
    {
        bs.RemoveFilter();
    }
    else
    {
        bs.Filter = string.Format("product_name LIKE '*{0}*'", metroTextBox1.Text);
    }
 


}

and is the datagrid view designed from designer that i need to filter

解决方案

Consider something more like this:

IList<ProductEntity> emp = HibernateDao.fetchDAta();

//seems no-op, did you miss a mapping call? : IList<ProductModel> products = new List<ProductModel>();

BindingSource bs = new BindingSource();
bs.DataSource = emp; //emp will need to be a bindable list; does fetchData do a ToList() ?

bs.Filter = "[product_name] = 'cornflakes'";

dataGridView1.Columns.Clear();
dataGridView1.AutoGenerateColumns = true;
dataGridView1.DataSource = bs;

You can't get DataGridView to show two properties in a single column, so e.quantity + " " + e.units type things won't work out. You'll have to add a property (not field) to ProductModel, that returns those two values as a single string

Databinding isn't a complicated thing. In some senses you're already doing part of it. That loop you had that iterated the data model and stuffed everything into the grid - databinding will do that for you, if you just set the datasource of the grid to a list that supports binding then the grid will create one row per list item (and in autogeneratecolumns mode it will make one column per simple property it finds). The more trick aspect of binding is that when you change the model (and you should change the data by changing the model, not programmatically altering the grid cells), the grid updates to reflect the changes

It helps achieve the separation of concerns that model/view/controller represents


Edit:

If HibernateDao.fetchDAta() returns something that doesn't implement the IBindingListView interface you could consider:

  1. To install the nuget package morelinq; it has methods to turn lists of objects into datatables, and datatables fully support filtering, OR

  2. To install the nuget package System.Linq.Dynamic; it can allow you to query things with linq by writing string expressions

Make a new project and completely replace the contents of Form1.vb with this demo:

Imports System.Linq.Dynamic
Imports MoreLinq

Public Class Form1

    Class Person
        Property Name As String
        Property Age As Integer

    End Class

    Private dgvDL As New DataGridView
    Private dgvBLV As New DataGridView
    Private tb As New TextBox
    Private people As List(Of Person)

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load



        Dim names() = {"John", "James"}
        people = names.Select(Function(x) New Person With {.Name = x, .Age = x.Length * 7}).ToList()


        'dynamic linq dgv 
        dgvDL.DataSource = people
        Me.Controls.Add(dgvDL)

        'morelinq DGV
        Dim bs As New BindingSource
        bs.DataSource = people.ToDataTable()
        dgvBLV.DataSource = bs
        Me.Controls.Add(dgvBLV)





        'irrelevant UI code
        AddHandler tb.TextChanged, AddressOf TextChange
        Me.Controls.Add(tb)
        dgvBLV.Location = New Point(dgvDL.Right, dgvDL.Top) 'place adjacent to above grid
        tb.Location = New Point(dgvDL.Left, dgvDL.Height)
    End Sub

    Private Sub TextChange(sender As Object, e As EventArgs)
        If (tb.Text = "") Then
            dgvDL.DataSource = people 'filter DL grid
            DirectCast(dgvBLV.DataSource, BindingSource).RemoveFilter() 'filter BLV grid
        Else
            dgvDL.DataSource = people.Where("Name == @0", tb.Text).ToList() 'filter DL grid
            DirectCast(dgvBLV.DataSource, BindingSource).Filter = $"[Name] = '{tb.Text}'" 'filter BLV grid
        End If
    End Sub


End Class

Note, if you're prepared to filter things using LINQ that doesnt use a built string filter, you don't need either of these helper libs; you can just use normal LINQ - see in the TextChange method I say .Where("Name == @0", tb.Text) - because Name is hardcoded here, this could just as easily be .Where(Function(x) x.Name = tb.Text). Dynamic LINQ only really makes your life a bit easier if you're constructing the left side too

--

Edit

C# version, not a huge departure from the VB. Not sure why my brain slipped into VB.NET, but I've left the VB above for you to compare with this, as a "that's how to read VB".. The two languages are nearly the same these days, but for a couple of keywords and semicolons, and it's always handy to know how to read other flavors of .NET:

using System.Linq.Dynamic;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using System;
using System.Collections.Generic;
using MoreLinq;

namespace WindowsFormsApp1
{


    public partial class Form1: Form
    {
        public Form1()
        {
            base.Load += Form1_Load;
        }

        public partial class Person
        {
            public string Name { get; set; }
            public int Age { get; set; }
        }

        private DataGridView dgvDL = new DataGridView();
        private DataGridView dgvBLV = new DataGridView();
        private TextBox tb = new TextBox();
        private List<Person> people;

        private void Form1_Load(object sender, EventArgs e)
        {
            var names = new string[] { "John", "James" };
            people = names.Select(x => new Person() { Name = x, Age = x.Length * 7 }).ToList();


            // dynamic linq dgv 
            dgvDL.DataSource = people;
            this.Controls.Add(dgvDL);

            // morelinq DGV
            var bs = new BindingSource();
            bs.DataSource = people.ToDataTable();
            dgvBLV.DataSource = bs;
            this.Controls.Add(dgvBLV);





            // irrelevant UI code
            this.tb.TextChanged += TextChange;
            this.Controls.Add(tb);
            dgvBLV.Location = new Point(dgvDL.Right, dgvDL.Top); // place adjacent to above grid
            tb.Location = new Point(dgvDL.Left, dgvDL.Height);
        }

        private void TextChange(object sender, EventArgs e)
        {
            if (tb.Text == "")
            {
                dgvDL.DataSource = people; // filter DL grid
                ((BindingSource)dgvBLV.DataSource).RemoveFilter(); // filter BLV grid
            }
            else
            {
                dgvDL.DataSource = people.Where("Name == @0", tb.Text).ToList(); // filter DL grid
                ((BindingSource)dgvBLV.DataSource).Filter = $"[Name] = '{tb.Text}'";
            } // filter BLV grid
        }
    }
}

这篇关于从C#中的实体填充的数据中过滤Datagrid View的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆