2012-03-26 9 views
0

ListViewと同期してモデルを保持することに問題があります(データバインディングは使用されていません)。WinForm ListViewで循環呼び出し(およびStackOverflowException)を回避する

  • ListViewの各項目は、リスト内のMyObjectインスタンスに対応します。
  • ListViewでは、MyObject.IsVisibleプロパティに対応するアイテムのチェック/チェック解除もできます。

現在のソリューション:MyObjectにリストの変更は、私がリストビューの内容を払拭し、そのアイテムを再生成RefreshItems()方法があるとき 。 私はListViewのItemCheckedイベントも実装しています。ユーザーがアイテムをチェック/チェック解除するたびに、対応するMyObject.IsVisibleプロパティを変更します。

問題は、MyObject.IsVisibleがバックエンドで変更された場合です。 ListViewの対応するチェックボックスは更新されません。

失敗の修正: どういうわけか、私は、ListViewコントロールにMyObject.IsVisibleのステータスの変更をカスケード接続する必要があります。たとえば、RefreshItems()を呼び出してRefreshItems()が実行されるたびに、ListView.ItemChangedイベントが自動的に呼び出されます。これにより、無限ループおよびstackoverflow例外が発生します。

  1. RefreshItemsは、()=>更新リストビューが変更され
  2. モデルに基づいて、リストビューは、したがってItemCheckedは何度でも我々は
  3. ItemCheckedを有するなどの多くの項目が呼び出されるが、リストビューに基づいてモデルを更新
  4. モデルが変更されると、再び始まります。 GOTO ItemChangedイベントハンドラ内1

が、私は、変化(すなわち、クリックすることで、ユーザーやアイテムを取り込むことにより、RefreshItems方法)を開始した人を検出する手段がないので、私から抜け出すするオプションを与えません無限ループ。

どうすればこの問題を解決できますか?

+0

"誰が変更を開始したかを検出する手段がありません" - これは真実ではありません。 – siride

+0

モデルがまだ新しい状態を反映していない場合にのみ、モデルの変更を実行するだけでは十分ではないでしょうか?例: 'ItemChecked'イベントが呼び出され、' IsChecked'プロパティが既に真である場合、何も変更せずにそのまま続行しますか?また、 'RefreshItems()'メソッドをもっと "知的"に変更し、リストビューを消去したり再作成するのではなく、既存のアイテムを変更することもできます。これは私の考えを助けるだろう。 –

答えて

1

RefreshItems()を呼び出す前に、ItemChangedのイベントハンドラをデタッチしようとします。
その後に再接続してください。

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

即時思考のカップル:itemChecked状態は、モデル内の異なる状態を設定した場合

1)のみRefreshItems()を呼び出します。モデルセッターで簡単にテストできます。

2)RefreshItems()にいくつかのフラグを付けて、GUIを更新していることに注意してください。このフラグが設定されている場合は、itemCheckedハンドラで何もしないでください。しかし、これは私にとって不愉快で厄介なものです。