I am still baffled finding out how to get a DataGridView updated automatically when changing the content of its DataSource without explicitely triggering DataGridView.Update()
. It seems there is no difference at all between DataTable
, List
, BindingList
as (direct) DataSource and as (indirect) DataSource with an additional BindingSource
which uses any of the former as DataSource.
The DataGridView I am actually using for this is non-editable and just shows entries which are updated by the corresponding entity code. My last attempt was with a BindingSource
that uses a BindingList
and manipulating the content of the BindingSource within the code.
I have omitted some methods here, which do not play a role for the basic problem.
Form:
private void FormLog_Load(object sender, EventArgs e) {
...
dgvLog.DataSource = Log.Current.SourceEntries;
...
}
private void ClearLog() {
Log.Current.RemoveAll();
}
public void UpdateDataSource() {
dgvLog.Update();
}
Entity (singleton class):
public class LogEntry {
public int ID { get; set; }
public string DateTime { get; set; }
public string Type { get; set; }
public string Event { get; set; }
public string Details { get; set; }
}
public class Log {
public BindingList<LogEntry> Entries { get; set; }
public BindingSource SourceEntries { get; set; }
public Log() {
Entries = new BindingList<LogEntry>();
SourceEntries = new BindingSource() { DataSource = Entries };
ReadAll();
}
public void Add(string type, string logEvent, string details = "") {
LogEntry entry = MapToDB(new LogEntry() {
Type = type,
Event = logEvent,
Details = details
});
DB.Write(QueryAdd(entry));
SourceEntries.Add(entry);
if (Config.Current.GetForm("Log") != null)
((FormLog)Config.Current.GetForm("Log")).UpdateDataSource();
}
public void ReadAll() {
for (int i = SourceEntries.Count - 1; i >= 0; i--) {
SourceEntries.RemoveAt(i);
}
DataTable dt = DB.Read(QueryReadAll());
if (dt != null) {
foreach (DataRow row in dt.Rows) {
SourceEntries.Add(MapToList(row));
}
}
if (Config.Current.GetForm("Log") != null)
((FormLog)Config.Current.GetForm("Log")).UpdateDataSource();
}
public void RemoveAll() {
DB.Write(QueryRemoveAll());
for (int i = SourceEntries.Count - 1; i >= 0; i--) {
SourceEntries.RemoveAt(i);
}
Add("I", "Log cleared");
}
This works but only when I call UpdateSource()
which calls dgvLog.Update()
by using a selfwritten FormStack in another singleton class which I would like to avoid. Of course, one could simply call dgvLog.Update()
within the form itself but, esp. with this log example, it is obvious that this does not help when updating data from/within another form while the form that displays the DataGridView is still opened in the background.
Also, as there is no difference (between using DataTable or List, etc. and BindingSource or not) I wonder what the benefit/purpose of BindingList and BindingSource are:
Is this the correct approach or am I missing something!?
By the way, I am using .NET v4.5.2.
It seems there is no difference at all between DataTable, List, BindingList as (direct) DataSource and as (indirect) DataSource with an additional BindingSource which uses any of the former as DataSource.
A BindingSource has a few uses
works but only when I call UpdateSource() which calls dgvLog.Update() by using a selfwritten FormStack in another singleton class which I would like to avoid. Of course, one could simply call dgvLog.Update() within the form itself but, esp. with this log example, it is obvious that this does not help when updating data from/within another form while the form that displays the DataGridView is still opened in the background.
Datagridview.Update() is concerned with repainting areas for the control that need it; it is nothing to do with committing changes to underlying data models. Perhaps you need EndEdit which finishes editing operations on the current row and commits them to the underlying data storage. This also happens when you click a different row in a grid. Bindingsource also have an EndEdit method. Mostly you don't need to call these methods yourself
To share data between forms pass the datatable the data is stored in and bind it through a bindingsource in the second form
Also, as there is no difference (between using DataTable or List, etc. and BindingSource or not) I wonder what the benefit/purpose of BindingList and BindingSource are:
DataTable is a collection of DataRow. A DataRow is at it's heart an object array. The end
Binding list is a list of whatever you want, such as your custom class Person. Arguably more useful ultimately, but it's comparing apple's and oranges. If instead you open up the DataSet Designer then you can specify tables that have named typed column. In that regard it's not a huge amount different from writing your own classes (it writes a large amount of good code on a short time though. I use them as data models sometimes