创建像 BindingList 这样的自定义集合,与 ListBox 配合使用来创建 ListChanging 事件
我遇到一种情况,我需要知道何时将在集合中添加/删除/修改某个项目。
我尝试通过在将触发这些事件的类中继承 BindingList ,但是“添加”事件不起作用。我发现它工作的唯一方法是重写 EndNew() 方法,但是我找不到一种方法来获取将在该方法中添加哪个对象(如果有人对此有解决方案,也可以) !)。
因此,构建了一个全新的类,它继承自 BindingList 的相同接口/类并实现了所有内容(但是,我没有继承 ICancelAddNew)。
我通过数据绑定将其绑定到我的列表框,但发现没有任何效果(listchanged 事件和 listchanging 事件)。如何在列表框中模拟 BindingList 行为?
非常感谢任何建议,我没有任何其他解决方法的想法
编辑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.Show("bla");
I have a situation where I need to know when an item is going to be added/removed/modified in the collection.
I tried by inheriting BindingList in a class that will trigger these events, however the "adding" event doesn't work. The only way I found it working is by overriding EndNew() method, however I don't find a way to get which object is going to be added in this method (if someone has a solution for this, it's ok too!).
So built a totally new class which inherits from same interfaces/class of BindingList and implemented everything (I didn't inherit, however, ICancelAddNew).
I bound it through databindings to my listbox and I find out that nothing works (listchanged events neither listchanging events). How can I simulate BindingList behavior on a listbox?
Any suggestion heavily appreciated, I don't have any other ideas for a workaround
EDIT 1:
This is my collection: http://pastie.org/1978601
And this is how I bind the collection to the 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);
Actually under subscribed events there is just a MessageBox.Show("bla");
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的集合不会检测现有项目中的属性更改,因为它在将项目添加到集合中时不会挂钩该项目的属性更改事件。
BindingList
会侦听项目上的 PropertyChanged,并在将项目添加到 BindingList 时触发 ListChanged 事件,并且它确实包含添加该项目的索引。在没有 WinForms 的测试应用程序中尝试一下。添加现有项目与 AddNew() 不同。 AddNew() 被调用时,AddingNew 事件才会被调用,并允许您提供新实例。
当涉及到 WinForms 时,事情会变得更加复杂。需要考虑CurrencyManager 和BindingSource。如果根本没有事件触发,则检查您是否正在使用您认为的CurrencyManager/BindingSource。
我认为框架中没有任何东西使用INotifyPropertyChanging,只有原始的INotifyPropertyChanged。您可能想在 BindingList 上使用 Reflector 来查看挂钩是如何完成的,然后尝试合并 INotifyPropertyChanging(如果您的项目支持)。
Your collection won't detect property changes in an existing item because it doesn't hook into the item's property changed events as it is added to the collection.
BindingList<T>
does listen to PropertyChanged on your item and does fire a ListChanged event when an item is added to the BindingList and it does include the index at which is is added. Try it in a test app without WinForms.Adding an existing item is not the same as AddNew(). The AddingNew event is only called when AddNew() is called and allows you to supply the new instance.
When WinForms is involved, things get more complicated. There is the CurrencyManager to think about and also BindingSource. If no events are firing at all then check to see if you are using the CurrencyManager/BindingSource you think you are.
I don't think anything in the framework uses INotifyPropertyChanging, only the original INotifyPropertyChanged. You might want to use Reflector on BindingList to see how the hooking is done and then try to incorporate INotifyPropertyChanging if your item supports it.
您遵循 MSDN 指南吗?您的集合类应该扩展
CollectionBase
并实现IBindingList
- 这应该没问题。此外,您可能希望集合item实现
IEditableObject
以支持*Edit
操作。但这不是必需的 - 更重要的是,您的集合项应该有一种方法可以在更改时通知父集合(通过遵循 MSDN 上提供的代码,或者使用例如INotifyPropertyChanged
)。您可以在
IBindingList
文档页面(Customer
类可在IEditableObject
文档页面)。Did you follow MSDN guidelines? Your collection class should extend
CollectionBase
and implementIBindingList
- and that should be fine.Also, you might want your collection item to implement
IEditableObject
in order to support*Edit
operations. This however is not required - more importantly, your collection item should have a way to notify parent collection when it changes (either by following code provided on MSDN, or using for exampleINotifyPropertyChanged
).You can find working binding sample implementing custom
CustomersList
onIBindingList
doc page (Customer
class can be found onIEditableObject
doc page).在清楚地了解您要寻找的内容之后,我将建议执行以下操作:
这是一个很棒的撤消框架,它提供了很多功能。
http://undo.codeplex.com/
这是示例,
http://blogs .msdn.com/b/kirillosenkov/archive/2009/07/02/samples-for-the-undo-framework.aspx
在您的情况下,最好不要尝试添加/编辑事件如果您存储其初始状态,则在添加/修改/删除事件后进行跟踪。因此,如果该项目被删除,那么在您之前的状态下,如果您从程序的启动状态开始跟踪,您将已经拥有该项目。
After getting clear idea of what you are looking for i will suggest following things
Here is a great undo framework which provides lot of functionality.
http://undo.codeplex.com/
Here is sample,
http://blogs.msdn.com/b/kirillosenkov/archive/2009/07/02/samples-for-the-undo-framework.aspx
And in your case, instead of trying to hook on adding/editing events, it's better to track after added/modified/deleted event if you store their initial state. So if the item was removed, in your previous state you will have the item already if you started tracking from the start state of your program.