2012-03-26 81 views
0

我有保持我的模型(表示为列表)与ListView同步(不使用数据绑定)的问题。避免与WinForm ListView的循环调用(和StackOverflowException)

  • ListView的每一项都与列表中的MyObject实例相对应。
  • ListView还允许检查/取消选中对应于MyObject.IsVisible属性的项目。

目前的解决方案: 每当MyObject的名单变化,我有一个RefreshItems()方法擦拭的ListView的内容,并重新生成它的项目。 我也实现了ListView的ItemChecked事件。每当用户选中/取消选中项目时,我都会修改相应的MyObject.IsVisible属性。

问题是在后端更改了MyObject.IsVisible时。 ListView中相应的复选框不会被更新。

失败的修复程序: 不知何故,我必须将MyObject.IsVisible的状态更改级联到ListView。例如,通过呼叫RefreshItems()。无论何时执行RefreshItems(),都会自动调用ListView.ItemChanged事件。这会导致一个infinit循环和stackoverflow异常。

  1. RefreshItems()=>更新基于
  2. 的ListView被改变模型的ListView,因此ItemChecked被调用许多次,我们有
  3. ItemChecked尽可能多的项目来更新基于所述的ListView模型
  4. 模型更改导致重新启动cicle。 GOTO 1

里面的ItemChanged事件处理程序,我也没办法来检测谁发起了变化(即,通过点击或通过填充项RefreshItems方法的用户),所以让我没有选择打出来的infinit循环。

我该如何解决这个问题?

+0

“我无法检测是谁发起了变更” - 这是不正确的。 – siride 2012-03-26 14:57:46

+0

仅在模型尚未反映新状态时才简单地对模型执行更改就足够了吗?例如:如果调用了“ItemChecked”事件并且“IsChecked”属性已经为true,那么不要更改任何内容并继续?另外:你可以很好地修改你的'RefreshItems()'方法,使其更加“智能”,并对现有的项目进行更改,而不是仅仅擦除和重新创建列表视图。这也有助于我的想法。 – 2012-03-26 15:04:33

回答

1

在调用RefreshItems()之前,我会尝试分离ItemChanged的事件处理程序。
然后重新连接。

listView.ItemChanged -= new ItemChangedEventHandler(myItemChangedEvent); 
RefreshItems(); 
listView.ItemChanged += new ItemChangedEventHandler(myItemChangedEvent); 
0

一对夫妇立即想法:

1)仅调用RefreshItems()如果itemChecked状态在模型中设置一个不同的状态。在您的模型设置器中轻松完成测试。

2)使用RefreshItems()中的一些标志来说明您正在更新GUI的事实。如果此标志已设置,则不要在您的itemChecked处理程序中执行任何操作。但是,这对我来说感觉很难受,很讨厌。