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.