Создайте пользовательскую коллекцию, подобную BindingList, которая работает со ListBox для создания события изменения списка

#c# #data-binding #listbox #bindinglist

#c# #привязка данных #listbox #bindinglist

Вопрос:

У меня ситуация, когда мне нужно знать, когда элемент будет добавлен / удален / изменен в коллекции.

Я попытался, унаследовав BindingList в классе, который будет запускать эти события, однако событие «добавление» не работает. Единственный способ, которым я обнаружил, что это работает, — переопределить метод EndNew () , однако я не нахожу способа узнать, какой объект будет добавлен в этот метод (если у кого-то есть решение для этого, это тоже нормально!).

Таким образом, был создан совершенно новый класс, который наследуется от тех же интерфейсов / класса BindingList и реализовал все (я, однако, не унаследовал ICancelAddNew).

Я привязал ее через databindings к своему listbox и обнаружил, что ничего не работает (ни события listchanged, ни события listchanging). Как я могу имитировать поведение BindingList в listbox?

Любое предложение высоко ценится, у меня нет других идей для обхода

РЕДАКТИРОВАТЬ 1:

Это моя коллекция: http://pastie.org/1978601 И вот как я привязываю коллекцию к ListBox

         SpellCasterManager.CurrentProfile.ButtonsMacro.ListChanged  = new ListChangedEventHandler(ButtonsMacro_ListChanged);
        SpellCasterManager.CurrentProfile.ButtonsMacro.ListChanging  = new Expand.ComponentModel.ListChangingEventHandler(ButtonsMacro_ListChanging);
gumpButton.DataBindings.Add("Value", SpellCasterManager.CurrentProfile.ButtonsMacro, "GumpIndex", false, DataSourceUpdateMode.OnPropertyChanged);
  

На самом деле в разделе подписанные события есть просто MessageBox.Показать («bla»);

Комментарии:

1. Может быть, вам следует опубликовать что-нибудь еще о том, «почему» вы хотите знать, когда элемент будет добавлен / удален / изменен? Потому что, если вы хотите заблокировать определенные действия пользовательского интерфейса до этого, вы можете настроить какое-либо событие или привязку, чтобы отключить операции добавления / удаления / изменения, пока выполняется какое-либо действие.

2. Что я хотел бы сделать, так это сохранить в списке «предыдущее значение» каждого свойства, измененного на элемент BindingList, потому что я хотел бы использовать его для чего-то подобного Ctrl Z

3. Итак, ясными словами, вы хотите функциональность отмены / повтора для вашего приложения? Тогда вам, возможно, придется многое изменить, потому что каждое изменение в свойстве и коллекции нужно будет сохранить как единицу работы, которую можно применить или удалить. Есть некоторый проект codeplex, который предоставляет некоторую структуру для реализации отмены / повтора.

4. Ну, я не буду использовать подход Memento, но я хотел бы использовать командный подход, вот почему я предпочитаю обнаруживать изменяющиеся и не измененные события

Ответ №1:

  • Ваша коллекция не обнаружит изменения свойств в существующем элементе, потому что она не подключается к событиям изменения свойств элемента при добавлении его в коллекцию.

  • BindingList<T> прослушивает PropertyChanged для вашего элемента и запускает событие ListChanged, когда элемент добавляется в BindingList, и оно включает индекс, по которому он добавлен. Попробуйте это в тестовом приложении без WinForms.

  • Добавление существующего элемента — это не то же самое, что AddNew(). Событие AddingNew вызывается только при вызове AddNew() и позволяет вам предоставить новый экземпляр.

  • Когда задействована WinForms, все становится сложнее. Нужно подумать о CurrencyManager, а также о BindingSource. Если события вообще не запускаются, проверьте, используете ли вы CurrencyManager / BindingSource, как вы думаете.

  • Я не думаю, что что-либо в фреймворке использует INotifyPropertyChanging, только исходный INotifyPropertyChanged. Возможно, вы захотите использовать Reflector в BindingList, чтобы посмотреть, как выполняется подключение, а затем попытаться включить INotifyPropertyChanging, если ваш элемент поддерживает это.

Комментарии:

1. Хорошо, хотя в вашем ответе говорится о многих вещах, важной является первая: моя коллекция не подключала события. Однако я думал, что CollectionBase справилась бы с этим за меня; я явно ошибался. Теперь это работает таким образом.

Ответ №2:

Вы следовали рекомендациям MSDN? Ваш класс collection должен быть расширен CollectionBase и реализован IBindingList — и это должно быть нормально.

Кроме того, вы можете захотеть, чтобы элемент вашей коллекции был реализован IEditableObject для поддержки *Edit операций. Это, однако, не требуется — что более важно, у вашего элемента коллекции должен быть способ уведомлять родительскую коллекцию при ее изменении (либо следуя коду, предоставленному в MSDN, либо используя, например INotifyPropertyChanged ).).


Вы можете найти рабочий пример привязки, реализующий пользовательскую, CustomersList на IBindingList странице документа ( Customer класс можно найти на IEditableObject странице документа).

Комментарии:

1. Спасибо за ваш ответ, я тестирую. Я сообщу вам новости об этом, еще раз спасибо.

2. @Fire-Dragon-DoL: не могли бы вы опубликовать какой-нибудь код, особенно. Add метод из вашей коллекции и как вы привязываетесь к элементу управления ..?

Ответ №3:

После получения четкого представления о том, что вы ищете, я предложу следующие вещи

Вот отличный фреймворк отмены, который предоставляет множество функциональных возможностей. http://undo.codeplex.com /

Вот пример, http://blogs.msdn.com/b/kirillosenkov/archive/2009/07/02/samples-for-the-undo-framework.aspx

И в вашем случае, вместо того, чтобы пытаться подключать события добавления / редактирования, лучше отслеживать после добавленного / измененного / удаленного события, если вы сохраняете их начальное состояние. Таким образом, если элемент был удален, в вашем предыдущем состоянии он уже будет у вас, если вы начали отслеживание с начального состояния вашей программы.

Комментарии:

1. Как я писал в ответе, я предпочитаю подход с шаблоном команд вместо подхода memento, вот почему мне нужно было отслеживать изменяющиеся события, и мне удалось заставить это работать.