kkh
kkh

Reputation: 4869

C# DataGridView not updated when datasource is changed

I have a list of object

List<MobilePhone> results;

so i added the list to the datagridview

dataGridView.DataSource = phase3Results;

so i have a few dropdown boxes which dictate the list results at any change of selected item in the dropdown boxes, so my list results changes, but on the datagridview its not reflected. is there any way to "refresh" the changes?

Upvotes: 19

Views: 47555

Answers (5)

Fadelovesky
Fadelovesky

Reputation: 131

As Suggested by Chris Gessler and Daniel, you have to use BindingList<> instead of List<>, and your model should properly implement INotifyPropertyChanged. But more important, check that your model is actually a Class. Datagridview will discard changes when your model is Records or Struct.

Upvotes: 1

Zeyad
Zeyad

Reputation: 626

One easy way is to use new BindingSource(object dataSource, "")

This will update the binding source and thus will update the table

For example:

dataGridView.DataSource = new BindingSource(phase3Results, "");

Upvotes: 1

Saeb Amini
Saeb Amini

Reputation: 24439

Quick and dirty solution:

dataGridView.DataSource = null;
dataGridView.DataSource = phase3Results;

Clean and correct solution:

Use a BindingList<T> instead of List<T> as your DataSource. List<T> does not fire events when its collection changes.

Also, if you additionally implement INotifyPropertyChanged for T, BindingList<T> automatically subscribes to property changes for each T in the collection and lets the view know about the change.

Upvotes: 46

Chris Gessler
Chris Gessler

Reputation: 23123

Try using a BindingList<> instead of List<> and (as already suggested by Daniel), implement INotifyPropertyChanged. However, I think you can also call .Refesh() if you didn't want to implement the INotifyPropertyChanged interface.

Here's an example ripped from here

public class Car : INotifyPropertyChanged
 {
   private string _make;
   private string _model;
   private int _year;

  public event PropertyChangedEventHandler PropertyChanged;

  public Car(string make, string model, int year)
   {
     _make = make;
     _model = model;
     _year = year;
   }

  public string Make
   {
     get { return _make; }
     set
     {
       _make = value;
       this.NotifyPropertyChanged("Make");
     }
   }

  public string Model
   {
     get { return _model; }
     set
     {
       _model = value;
       this.NotifyPropertyChanged("Model");
     }
   }

  public int Year
   {
     get { return _year; }
     set
     {
       _year = value;
       this.NotifyPropertyChanged("Year");
     }
   }

  private void NotifyPropertyChanged(string name)
   {
     if(PropertyChanged != null)
       PropertyChanged(this, new PropertyChangedEventArgs(name));
   }
 }

_dgCars.AutoGenerateColumns = false;

DataGridViewTextBoxColumn makeColumn = new DataGridViewTextBoxColumn();
 makeColumn.DataPropertyName = "Make";
 makeColumn.HeaderText = "The Car's Make";

DataGridViewTextBoxColumn modelColumn = new DataGridViewTextBoxColumn();
 modelColumn.DataPropertyName = "Model";
 modelColumn.HeaderText = "The Car's Model";

DataGridViewTextBoxColumn yearColumn = new DataGridViewTextBoxColumn();
 yearColumn.DataPropertyName = "Year";
 yearColumn.HeaderText = "The Car's Year";

_dgCars.Columns.Add(makeColumn);
 _dgCars.Columns.Add(modelColumn);
 _dgCars.Columns.Add(yearColumn);

BindingList<Car> cars = new BindingList<Car>();

cars.Add(new Car("Ford", "Mustang", 1967));
 cars.Add(new Car("Shelby AC", "Cobra", 1965));
 cars.Add(new Car("Chevrolet", "Corvette Sting Ray", 1965));

_dgCars.DataSource = cars;

Upvotes: 16

Daniel Lorenz
Daniel Lorenz

Reputation: 4346

You need to implement the INotifyPropertyChanged interface on the object that is storing the data. Each property needs to raise that event during the set call of a property if the value changed. Then the grid will automatically get the update.

Upvotes: 2

Related Questions