ObjectListView Update (220.127.116.11): Find, Select, & Property Paths
Posted on May 6, 2007
Note: You can download the complete implementation here.
I just posted a new version of ObjectListView that fixes a couple of bugs and adds some minor usability enhancements.
I’ve been using ObjectListView more in different projects, and I’m feeling the pain points. Foremost, a complete IBindingListView implementation means that interaction with Windows Forms controls works smoothly, but that doesn’t mean it’s easy for the developer to use.
I don’t like working with PropertyDescriptors as method parameters. In order to find a list item via IBindingList,.Find(), you need to get the descriptors for the list item type from TypeDescriptor, and then look up the correct one by the property name. Awkward. Moreover, all that Find() gives you is the first item found for which one property equals a specified value. I’ve added two more useful Find() overloads. One takes a string expression that can be an arbitrarily complex set of property comparisons (using the same syntax as the Filter property). The other allows you to specify a Predicate delegate to provide a comparison in code. Given these, the original Find() required for IBindingList seems unlikely to be used, so I changed it to an explicit interface implementation. This has the effect of hiding the overload from the publicly exposed class methods, but still making it available to consumers of IBindingList.
One of the useful methods of DataTable is Select(), which returns the set of DataRows in the table that match a given criteria. Now clearly, you could iterate over the items in the view yourself and evaluate each, but having this built in to ObjectListView is very convenient. As with Find(), I added two versions, one that takes a string expression, and the other that takes a delegate. The return value of Select is a list of items that match the criteria.
Something I’ve had in mind for a while is being able to filter on list items based on the values of properties of properties. You could use FilterPredicate to specify such a filter with a delegate, but it would be even more convenient to use an expression like “Customer.AccountRep.Department = 2”. The new version 18.104.22.168 supports this kind of property path in the Filter property, Find() and Select(). Currently, changing the value of one of the sub-properties specified in a Filter property path will not cause the view to be updated. I need to do more work before I have an efficient implementation of the notification logic.
Item Deletion Events
ObjectListView has always provided the ListChanged event, which specifies an action type (ListChangedType). One of the actions reported is Deleted, indicating that a list item has been removed. Unfortunately, only the index of the item deleted is available at the time the event is raised; the item has already been removed. I’ve added the RemovingItem event, which is raised just before an item is removed from the list. This event is only raised when an item is removed through a method of ObjectListView (for example, view.Remove() or view.RemoveAt()). If an item is removed through a method of the underlying list, the deletion is reported to ObjectListView after the fact, so RemovingItem cannot be raised.
As always, a few bugs are fixed, and some minor clean-up done. See the change log for details.
As I mentioned, there’s work yet to be done in keeping the view up to date as sub-properties specified in the Filter expression change. I’m also working on dynamic properties that can be added to the view. These would be analogous to the expression columns supported by DataTable.
I’m also excited to be presenting ObjectListView at the Portland Code Camp in two weeks! I think it will be hard to explain it all in an hour. I’ll just have to talk really, really fast.