I reckon the problem of C# win forms not being repainted well in certain circumstances is covered in different places, however, I didn't manage to solve my problems by using the simple snippets I found on the web.
My problem : on a form I have a listView, which I associate to a custom data holder (2 columns, a key and a last update date). From diverse places, I need to call the updateTime(key) method which then replicated the changes in the GUI. The model gets changed but my listView never.
I have a form containing a ListView that looks like that :
partial class VolsPane : UserControl, IGUIPane
{
private ListView listView1;
private ListModel listModel1; //ListModel is 100% homemade
...
public VolsPane()
{
...
listModel1.setList(listView1);
}
}
And the class holding data for my listView is like that :
class ListModel
{
private Dictionary<string, DateTime> Underlying;
private ListView list;
...
public ListModel(string nexusKey)
{
...
}
...
public void setList(ListView list)
{
this.list = list;
}
public void updateTime(string ric)
{
Underlying[ric] = DateTime.UtcNow;
updateView();
}
public void updateView()
{
this.list.Clear();
this.list.Items.AddRange(this.underlyingToListItems());
}
...
public ListViewItem[] underlyingToListItems()
{
ListViewItem[] res = new ListViewItem[Underlying.Keys.Count];
int i = 0;
foreach (string ric in Underlying.Keys)
{
res[i] = new ListViewItem(new string[] { ric, Underlying[ric].ToString("MMM-dd hh:mm:ss") });
i++;
}
return res;
}
}
I do realize the problem is in my updateView(). In debug, the code goes there definitely. Believing the problem was to be solved with an asynchronous "invoke", I referred to this post which appeared to be a reference : Stack overflow : Automating the invoke...
Then tried this :
private void updateView()
{
if (this.list.InvokeRequired)
{
this.list.Invoke(new MethodInvoker(() => { updateView(); }));
}
else
{
this.list.Items.Clear();
//this.list.Clear();
this.list.Items.AddRange(this.underlyingToListItems());
}
}
It builds but has no effect. In debug mode, never goes in the 'if' branch, always the 'else'.
Then this :
private void updateView()
{
this.list.Invoke((MethodInvoker)delegate
{
this.list.Items.Clear();
//this.list.Clear();
this.list.Items.AddRange(this.underlyingToListItems());
});
}
I get an "InvalidOperationException : Invoke or BeginInvoke cannot be called on a control until the window handle has been created."
What is the obvious thing I must be missing here ? Or is my problem actually not the one i think ?
Thanks guys !