【发布时间】:2011-12-30 06:58:42
【问题描述】:
我认为 C# win 表单在某些情况下不能很好地重绘的问题在不同的地方都有介绍,但是,我没有设法通过使用我在网上找到的简单 sn-ps 来解决我的问题。
我的问题:在一个表单上,我有一个 listView,我将它关联到一个自定义数据持有者(2 列、一个键和一个最后更新日期)。从不同的地方,我需要调用 updateTime(key) 方法,然后复制 GUI 中的更改。模型会改变,但我的 listView 永远不会。
我有一个包含 ListView 的表单,看起来像这样:
partial class VolsPane : UserControl, IGUIPane
{
private ListView listView1;
private ListModel listModel1; //ListModel is 100% homemade
...
public VolsPane()
{
...
listModel1.setList(listView1);
}
}
为我的 listView 保存数据的类是这样的:
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;
}
}
我确实意识到问题出在我的 updateView() 中。在调试中,代码肯定会去那里。相信问题将通过异步“调用”来解决,我参考了这篇似乎是参考的帖子:Stack overflow : Automating the invoke...
然后试试这个:
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());
}
}
它构建但没有效果。在调试模式下,永远不会进入 'if' 分支,始终是 'else'。
那么这个:
private void updateView()
{
this.list.Invoke((MethodInvoker)delegate
{
this.list.Items.Clear();
//this.list.Clear();
this.list.Items.AddRange(this.underlyingToListItems());
});
}
我收到“InvalidOperationException:在创建窗口句柄之前无法在控件上调用 Invoke 或 BeginInvoke。”
我必须在这里遗漏什么明显的东西?还是我的问题实际上不是我想的?
谢谢大家!
【问题讨论】:
标签: c# winforms multithreading user-interface invoke