Предотвращение циклического вызова (и исключения StackOverflowException) с помощью WinForm ListView - PullRequest
0 голосов
/ 26 марта 2012

У меня проблема с синхронизацией модели (представленной в виде списка) с ListView (привязка данных не используется).

  • Каждый элемент ListView соответствует экземпляру MyObject в списке.
  • ListView также позволяет проверять / снимать отметку со своих элементов, соответствующих свойству MyObject.IsVisible.

Текущее решение: Всякий раз, когда меняется список MyObject, у меня естьRefreshItems() метод, который стирает содержимое ListView и восстанавливает его элементы.Я также реализовал событие ItemChecked объекта ListView.Всякий раз, когда пользователь проверяет / снимает отметку с элемента, я изменяю соответствующее свойство MyObject.IsVisible.

Проблема в том, что MyObject.IsVisible изменяется в бэкэнде.Соответствующий флажок в ListView не будет обновляться.

Неисправное исправление : каким-то образом мне приходится каскадно изменять состояние MyObject.IsVisible для ListView.Например, позвонив по номеру RefreshItems().Всякий раз, когда выполняется RefreshItems (), события ListView.ItemChanged автоматически вызываются.Это приводит к исключению бесконечного цикла и переполнению стека.

  1. RefreshItems () => обновляет ListView на основе модели
  2. ListView изменяется, следовательно, ItemChecked вызывается столько раз, сколько у нас элементов
  3. ItemCheckedобновляет модель на основе ListView
  4. , изменение модели вызывает повторный запуск цикла.GOTO 1

Внутри обработчика событий ItemChanged у меня нет средств, чтобы определить, кто инициировал изменение (т. Е. Пользователь нажал или метод RefreshItems, заполнив элементы), поэтому у меня нет возможности прерыватьиз бесконечного цикла.

Как я могу решить эту проблему?

Ответы [ 2 ]

1 голос
/ 26 марта 2012

Я попытаюсь перед вызовом RefreshItems () отсоединить обработчик событий для ItemChanged.
И прикрепите потом.

listView.ItemChanged -= new ItemChangedEventHandler(myItemChangedEvent);
RefreshItems();
listView.ItemChanged += new ItemChangedEventHandler(myItemChangedEvent);
0 голосов
/ 26 марта 2012

Пара немедленных мыслей:

1) Вызывать RefreshItems() можно только в том случае, если состояние itemChecked устанавливает РАЗНОЕ состояние в вашей модели. Легко выполняется с помощью теста в вашей модели сеттера.

2) Используйте некоторый флаг в RefreshItems(), чтобы отметить тот факт, что вы обновляете графический интерфейс. Если этот флаг установлен, то ничего не делайте в обработчике itemChecked. Тем не менее, мне это кажется хакерским и неприятным.

...