SortedBindingList.SourceChanged (ListChangedType.ItemAdded behavior)

SortedBindingList.SourceChanged (ListChangedType.ItemAdded behavior)

Old forum URL: forums.lhotka.net/forums/t/656.aspx


tsmo posted on Tuesday, July 18, 2006

I'm adding items to a SortedBindingList, and it isn't sorting them.  Stepping through the code, I found that DoSort() isn't called in SourceChanged after ListChangedType.ItemAdded in the Add() case (e.NewIndex == _list.Count -1) but it is called in the Insert() case (e.NewIndex != _list.Count -1).  Is this a bug?

When I added DoSort() to right before the end of that block, it behaved as expected.  What am I missing?

Thanks,
tsmo

The code in question:

private void SourceChanged(
      object sender, ListChangedEventArgs e)
    {
      if (_sorted)
      {
        switch (e.ListChangedType)
        {
          case ListChangedType.ItemAdded:
            T newItem = _list[e.NewIndex];
            if (e.NewIndex == _list.Count - 1)
            {
              object newKey;
              if (_sortBy != null)
                newKey = _sortBy.GetValue(newItem);
              else
                newKey = newItem;

              if (_sortOrder == ListSortDirection.Ascending)
                _sortIndex.Add(
                  new ListItem(newKey, e.NewIndex));
              else
                _sortIndex.Insert(0,
                  new ListItem(newKey, e.NewIndex));
              if (!_initiatedLocally)
                OnListChanged(
                  new ListChangedEventArgs(
                  ListChangedType.ItemAdded,
                  SortedIndex(e.NewIndex)));
            }
            else
              DoSort();
            break;
...

RockfordLhotka replied on Tuesday, July 18, 2006

This is intended behavior. The reason is that SortedBindingList can be used as a data source to a DataGridView control in Windows Forms, and if it resorted instantly on adding new rows the user experience for in-place editing would be horrible - unusable actually (I tried Cool [H]).

So when adding new items to the sorted list, the items aren't resorted unless you reapply the sort by calling ApplySort() again (or do some other operation to the list that does trigger a sort).

Brian Criswell replied on Tuesday, July 18, 2006

Was the unusable behaviour because it would resort an item after you edited a cell?

RockfordLhotka replied on Tuesday, July 18, 2006

It was worse than that. Because when the user arrows down onto the bottom row of the grid is the point at which a new item is created and added to the list. At that instant the new (and probably empty) row gets resorted to the top of the list, leaving the user near the bottom, wondering where their new row went??
 
Rocky


From: Brian Criswell [mailto:cslanet@lhotka.net]
Sent: Tuesday, July 18, 2006 3:39 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] SortedBindingList.SourceChanged (ListChangedType.ItemAdded behavior)

Was the unusable behaviour because it would resort an item after you edited a cell?



Brian Criswell replied on Tuesday, July 18, 2006

Okay, so I threw together a test with a DataGridView and a DataView.  How does the DataView know to sort only after the user has finished editing a row and moved off of that row?

RockfordLhotka replied on Tuesday, July 18, 2006

I don't know - I only tested with the DataGridView.
 
Both DansDreams and I spent a lot of time on this - with a form that has two DataGridView controls - one bound to the original list, the other to the sorted list - both live and supporting in-place add/edit/delete. The goal was to be able to do any operation in either grid and have a meaningful result for the user.
 
This is the same testing technique I'm doing for the FilteredBindingList in 2.1 - and I'm finding similar oddities. Like you can't filter out a new row as it is added - and almost all new rows would get filtered out because they wouldn't meet the criteria - stuff like that.
 
Rocky


From: Brian Criswell [mailto:cslanet@lhotka.net]
Sent: Tuesday, July 18, 2006 4:59 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] RE: SortedBindingList.SourceChanged (ListChangedType.ItemAdded behavior)

Okay, so I threw together a test with a DataGridView and a DataView.  How does the DataView know to sort only after the user has finished editing a row and moved off of that row?



Brian Criswell replied on Tuesday, July 18, 2006

RockfordLhotka:
This is the same testing technique I'm doing for the FilteredBindingList in 2.1 - and I'm finding similar oddities. Like you can't filter out a new row as it is added - and almost all new rows would get filtered out because they wouldn't meet the criteria - stuff like that.
 
Rocky

Could you just add something similar to "OR IsNew = 'True'" to the filter if you know you are going to be doing in place editing?

RockfordLhotka replied on Tuesday, July 18, 2006

Well the thing is, the filter itself is a pluggable component - so you can write your own custom filters for different purposes or needs. The default filter is fairly simplistic, although often useful. But I can't assume any given filter will provide specific functionality.

I think I have a pretty workable solution at the moment - it passes all my tests anyway, and it is composable with SortedBindingList, which is really cool.

Brian Criswell replied on Wednesday, July 19, 2006

After doing some more research, I realised that the DataView behaves the way it does because it exposes a DataRowViewCollection, not a DataRowCollection.  The DataRowView implements IEditableObject, and the changes made are not made until you change rows.  I will do some research into this to see how to modify our object views to use this concept.  With luck, we will have views that can sort and filter immediately but will behave properly in a DataGridView.

jh72i replied on Tuesday, October 21, 2008

Hi folks,
Having an unexpected problem with FilteredBindingList. When I add a new item to the underlying datasource it appears in the filtered view regardless of whether or not it passes the filtering criteria. You folks have any thoughts on solving this particular problem?

I know you have problems with adding items before they have properties set (so they might be filtered out before you can even edit them, etc.) but i already have all the properties set.

I have a number of filtered views on a single datasource. I add to the datasource and the new items appears in each list (instead of the one it should). I'm in a bind so I will probably have to 'plumb' an ...if(provider.Invoke(newItem, _filter).....an at the +++ lines below but would love to hear what the 'real' solution should be.

thanks

   private void SourceChanged(object sender, ListChangedEventArgs e)
    {
...        switch (e.ListChangedType)
        {
          case ListChangedType.ItemAdded:
            listIndex = e.NewIndex;
            // add new value to index
            newItem = _list[listIndex];
            if (_filterBy != null)
              newKey = _filterBy.GetValue(newItem);
            else
              newKey = newItem;

+++++ hang on - don't add until you see if it matches the filter +++++++
            _filterIndex.Add(
              new ListItem(newKey, listIndex));
           

Copyright (c) Marimer LLC