#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, вот почему мне нужно было отслеживать изменяющиеся события, и мне удалось заставить это работать.