Is this aproach the best that exist to databind a datagridview?
I've seen many people with problems binding datagridviews and after a lot of work I found this as the best method. I hope it helps other people, and someone can add an improvement.
Step 1) Create the dataGridView and its columns with the editor.
Step 2) Create an object that represents a row in the datagridview.
This object may have as many instances of database entities as you need. Here's an example with two objects (two columns in the datagridview)
public class ObjectToShow
{
MyDatabaseObject myDatabaseObject = new MyDatabaseObject();
public ObjectToShow(MyDatabaseObject myDatabaseObject)
{
this.myDatabaseObject = myDatabaseObject;
}
public string Data1 //to asign to a datagridview column
{
get { return myDatabaseObject.data1; }
set { myDatabaseObject.data1 = value; NotifyPropertyChanged("Data1")}
}
public string Data2 //to asign to another datagridview column
{
get { return myDatabaseObject.data2; }
set { myDatabaseObject.data2 = value; NotifyPropertyChanged("Data2"); }
}
//This is to notify the changes made to the object directly and not from the control. This refreshes the datagridview.
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Step 3) In the Form create a BindingList of ObjectToshow and a bindingSource as follow
BindingList<ObjectToshow> ObjectToShow_list = new BindingList<ObjectToshow>();
BindingSource bindingSource = new BindingSource();
Step 4) Create the bindings this way
//if we don't put this, each public property in ObjectToshow will generate a new column in the datagridview
//I think it's best to create the columns from the editor.
dataGridView1.AutoGenerateColumns = false;
//database -> <- bindingList -> <- bindingSource -> <- datagridview <- user
bindingSource.DataSource = ObjectToShow_list;
dataGridView1.DataSource = bindingSource;
dataGridView1.Columns["Column_Data1"].DataPropertyName = "Data1";
dataGridView1.Columns["Column_Data2"].DataPropertyName = "Data2";
Step 5) query the database
//Example bringing all the data from a database table. This should be done in a controller class.
My_DBModel DB_context = new My_DBModel();
List<myDatabaseObject> myDatabaseObject_list = DB_context.myDatabaseObject.ToList();
//Clear de previous data
ObjectToShow_list.Clear();
//Add the queried elements to the bindingList
foreach (myDatabaseObject item in myDatabaseObject_list)
{
ObjectToshow objectToshow = new ObjectToshow(item);
ObjectToShow_list.Add(objectToshow);
}
Step 6) Modify the data from the bindingList or the datagridview as you want. Then DB_context.saveChanges().
To add data, add it directly to DB_context.myDatabaseObject.Add(new ...) and query the database again; If you want to add it from the datagridview I think you have to handle the event and add it to the context anyway.
This is what I do and it works, but I'm not sure if it's the best way. Thanks in advance.
Step 5)
is pretty unclear to me. One of the main advantages of your approach is decouple the Database Model from the business model. You do that by creating a class that can hold properties from several tables. But then you query only one table. The reason I'm writing this is that when you want to get data from several tables but put it in one object you would want to do as much work as possible on the Database Server side so when your query is executed it fetches the data so that you can directly populate the object properties. – Leron_says_get_back_MonicaMy_DBModel DB_context = new My_DBModel();
in the controller is not what you want. What I think is better is another project to take care for your data access. – Leron_says_get_back_MonicaRepository
pattern,Unit Of Work
pattern, some Dependency container likeUnity
orNInject
, and also you might also want to research why using theDbContext
directly from the controller is not the best approach in MVC pattern. – Leron_says_get_back_Monica