简体   繁体   中英

C#, Use Databinding to fill DatagridView and Filter Rows

I am new to winForm and I am trying to use a DatagridView to display some information from my class. I use the following code to display my information:

        public class Dataclass
        {
           public string FileName {get; set} 
           public string FieldsTotal {get; set} 
           public string Quantity{get; set} 
           public string SelectionColumnTexte {get; set}

           public Dataclass(string fileName, string fieldsTotal, string quantity, string selectionColumnTexte)
           {
               FileName = fileName;
               FieldsTotal = fieldsTotal;
               Quantity= quantity;
               SelectionColumnTexte = selectionColumnTexte;
           }
        }

        public static DataTable dataTable = new DataTable();
        public static DatagridView dgv = this.Mydatagridview;
        public static BindingSource bindingSource = new BindingSource();
        public static List<Dataclass> MyDataclass = new List<Dataclass>();
        MyDataclass.Add(new Dataclass("Name1","10","10","Select")); 
        MyDataclass.Add(new Dataclass("Name2","20","20","Select")); 
        MyDataclass.Add(new Dataclass("Name3","30","30","Select")); 
        public static void InitializeDataGridView()
        {
            FillBindingSourceWithClass();
            ModifyDatagridViewParameters();
            CreateDifferentColumnAndFillItWithData();
        }

        public static void FillBindingSourceWithClass()
        {
           foreach (Dataclass Myclass in MyDataclass)
            {
                bindingSource.Add(Myclass);
            }
        }
        public static void ModifyDatagridViewParameters()
        {
            dgv.AutoGenerateColumns = false;
            dgv.AutoSize = true;
            dgv.DataSource = bindingSource;
        }
        public static void CreateDifferentColumnAndFillItWithData()
        {
            DataGridViewColumn FileNameColumn = new DataGridViewTextBoxColumn();
            FileNameColumn.Name = "File Name";
            FileNameColumn.DataPropertyName = "FileName";
            dgv.Columns.Add(FileNameColumn);
            DataGridViewColumn FieldsTotalColumn = new DataGridViewTextBoxColumn();
            FieldsTotalColumn.Name = "FieldsTotal";
            FieldsTotalColumn.DataPropertyName = "FieldsTotalInFile";
            dgv.Columns.Add(FieldsTotalColumn);
            DataGridViewColumn QuantityColumn = new DataGridViewTextBoxColumn();
            QuantityColumn.Name = "Quantity";
            QuantityColumn.DataPropertyName = "Quantity";
            dgv.Columns.Add(QuantityColumn);
            DataGridViewColumn SelectionColumn = new DataGridViewButtonColumn();
            SelectionColumn.Name = "File Selection (Click to multiselect)";
            SelectionColumn.DataPropertyName = "SelectionColumnTexte";
            dgv.Columns.Add(SelectionColumn );
         }

At this point my datagridview generate correctly and all my data is visible. Now I want to filter lines by the File Name Columns and I don't know how I can do that. I have another variable (containing a combobox) to select the file name I want to filter by. I try to use the BindingSource.Filter but with no success. Can someone help me with that or explain to me if datagridview structure is too bad? I haven't DataTable (I did not understand its usefulness of it.)

Well… the main problem you will have with using a List<myClass> with a BindingSource is that List<> does not implement the IBindingListView interface. A DataTable does implement this interface and in most examples, you will see a DataTable used and not a List<> .

Unless you specifically need to use the BindingSource it may be easier to simply use LINQ to filter the List<myClass> and use it as a data source to the grid. NOTE: there are many advantages to using a BindingSource and depending on your needs, you may want to change from a List<myClass> to a DataTable .

I will assume for this simple example that you want to use a List<Dataclass> and below is an example of how you can filter it. Your current code has many typos and it is curious why you did not copy/paste the original code as opposed to re-typing it as it appears you have done.

To start, it appears the code is unnecessarily adding the “Button” text to the data source…? … The “Select” text is added to the DATA SOURCE like…

MyDataclass.Add(new Dataclass("Name1","10","10","Select"));

? … This is very odd and there appears to be no reason to have the string “Select” INSIDE the data source for each Dataclass object. So, I have removed that field from the Dataclass Class.

Instead, you can add the DataGridViewButtonColumn with the “Select” text displayed in all the buttons. The problem with the current code is the line of code…

DataGridViewColumn SelectionColumn = new DataGridViewButtonColumn();

The grids button column has two (2) properties we need to set to set up the “Select” text as we want… however the code above is setting SelectionColumn to a generic DataGridViewColumn on the left side… so, the properties we need will not available. Therefore, we need to change it to a DataGridViewBUTTONCOLUMN to get the properties we need. Something like below should work…

DataGridViewButtonColumn SelectionColumn = new DataGridViewButtonColumn();
SelectionColumn.Name = "Select"; 
SelectionColumn.Text = "Select";
SelectionColumn.UseColumnTextForButtonValue = true;
SelectionColumn.HeaderText = "File Selection (Click to multiselect)";

This should eliminate the need to add the “Select” text to the data source.

The code below drops the BindingSource and uses the List<Dataclass> as a DataSource to the grid. I simplified the code to just two methods and most of the work is done in the forms load event.

We will first set the List<Dataclass> as a global variable, however you could avoid this if needed. Also, the line of code below is odd and it is unclear where it is called, however you will have a problem with the line of code…

public static DatagridView dgv = this.Mydatagridview;

There is really NO need for this… Mydatagridview is ALREADY exposed to the code and there is not need to “create” a new variable for it. Therefore, is what I did is simply renamed the grid on the form to dgv . This eliminated my need to change all the dgv references in the current code.

Try the code below and it should produce the same results in a simpler fashion…

First the altered Dataclass …. With the removed SelectionColumnTexte property.

public class Dataclass {
  public string FileName { get; set; }
  public string FieldsTotal { get; set; }
  public string Quantity { get; set; }

  public Dataclass(string fileName, string fieldsTotal, string quantity) {
    FileName = fileName;
    FieldsTotal = fieldsTotal;
    Quantity = quantity;
  }
} 

Then the code to fill the grid with data…

public List<Dataclass> MyDataclass = new List<Dataclass>();

public Form1() {
  InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e) {
  MyDataclass.Add(new Dataclass("Name1", "10", "10"));
  MyDataclass.Add(new Dataclass("Name2", "20", "20"));
  MyDataclass.Add(new Dataclass("Name3", "30", "30"));
  dgv.AutoGenerateColumns = false;
  dgv.AutoSize = true;
  dgv.DataSource = MyDataclass;
  CreateDifferentColumnAndFillItWithData();
}


public void CreateDifferentColumnAndFillItWithData() {
  DataGridViewColumn FileNameColumn = new DataGridViewTextBoxColumn();
  FileNameColumn.Name = "File Name";
  FileNameColumn.DataPropertyName = "FileName";
  dgv.Columns.Add(FileNameColumn);
  DataGridViewColumn FieldsTotalColumn = new DataGridViewTextBoxColumn();
  FieldsTotalColumn.Name = "FieldsTotal";
  //FieldsTotalColumn.DataPropertyName = "FieldsTotalInFile";
  FieldsTotalColumn.DataPropertyName = "FieldsTotal";
  dgv.Columns.Add(FieldsTotalColumn);
  DataGridViewColumn QuantityColumn = new DataGridViewTextBoxColumn();
  QuantityColumn.Name = "Quantity";
  QuantityColumn.DataPropertyName = "Quantity";
  dgv.Columns.Add(QuantityColumn);
  DataGridViewButtonColumn SelectionColumn = new DataGridViewButtonColumn();
  SelectionColumn.Name = "Select"; 
  SelectionColumn.Text = "Select";
  SelectionColumn.UseColumnTextForButtonValue = true;
  SelectionColumn.HeaderText = "File Selection (Click to multiselect)";
  dgv.Columns.Add(SelectionColumn);
}

And finally, I added a Button to the form to demonstrate how you could filter the data in the grid….

private void button1_Click(object sender, EventArgs e) {
  var filter = MyDataclass.Where(x => x.FileName == "Name2").ToList();
  dgv.DataSource = filter;
}

Then another Button to UN-filter the grid.

private void button2_Click(object sender, EventArgs e) {
  dgv.DataSource = MyDataclass;
}

I hope this makes sense and helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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