Sorting & Filtering - SortedBindingList? LINQ to CSLA? v4?

Sorting & Filtering - SortedBindingList? LINQ to CSLA? v4?

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


BigPines2 posted on Thursday, October 07, 2010

In the following old post, Rocky suggests using LINQ to CSLA as a replacement for the old way of filtering/sorting collections: http://forums.lhotka.net/forums/p/199/1189.aspx

Apparently LINQ to CSLA has been done away with in v4. Is the CSLA 4 LinqObservableCollection only for Silverlight? Did we loose the ability to index properties? Is there an example of how to use this new functionality?

I am still using v3.8.3 but I want to use the best method of filtering/sorting possible. My resulting filtered/sorted collection does need to subscribe to an observer channel if at all possible. I am currently using Petar Kozul's old ActiveObjects for the observer stuff. If moving to v4 would help, I may be willing to do that.

All the changes to the framework have become confusing to me. What is the recommended approach?

Rocky, The framework has changed enough that I think it is time for another book. I know that takes time but I will be first in line to buy it. Big Smile

Mike

JonnyBee replied on Thursday, October 07, 2010

The general rule is quite simple:

WinForms - SortedBindingList/FilteredBindingList due to requirement for IBindingList support
WPF, SL, ASP.NET - use Linq2Objects or standalone projects like I4O to create indexes over collections of object. (IObservableCollection/IEnumerable)

New in Csla4 is the extension method ToSyncList() that can be applied to Linq queries that return a LinqObservableCollection wrapper over the original list.

BigPines2 replied on Thursday, October 07, 2010

Thanks for the reply.

Since this current project happens to be a WinForms CSLA v3.8.3 app, I will continue to use SortedBindingList/FilteredBindingList then. Does CSLA v4 continue to have these object types as well?

My next projext will be ASP.NET so I guess I will have to look into I4o for that or move to CSLA v4 to use LinqObservableCollection.

Do I have it correct?

Mike

RockfordLhotka replied on Thursday, October 07, 2010

CSLA 4 continues to have SortedBindingList/FilteredBindingList, because it continues to support Windows Forms.

You can use those with ASP.NET too, that's no problem. Or you can use LINQ queries.

i4o offers indexing of collections. You should be aware that this is only useful if you are going to do numerous queries over the same instance of the collection, otherwise you'll never offset the cost of creating the index. In other words, if you index a list and then do one query and then discard the list, you'll lose performance because creating the index is more costly than a single query without an index.

Since most web applications have a stateless server, it would never make sense to index a collection. Only if you store a collection in Session and do multiple queries over time could it pay off - and even then it probably only pays off if Session is running in-proc - because if it is out-of-proc Session gets serialized, which means your index would get serialized, and that's not cheap either.

Fun stuff :)

Michael replied on Wednesday, October 27, 2010

I'm still having major issues with the SortedBindingList and FilteredBindingList for editable collections. They work great for read-only lists, but for live BLB's they cause EditLevelMismatch exceptions. I first reported it two years ago here: http://forums.lhotka.net/forums/p/4991/28360.aspx#28360

Does anyone use them for editable lists? I just tried wrapping the children in the latest RootChildGrandchildWinFormTest, run it up, sort on a column header, click Apply and it crashes straight away.

We're using 3.8.3 and this issue has come up again because I have a new screen which desperately needs sort and search functionality.

Could someone please try this?

Kind regards
Michael

JonnyBee replied on Thursday, October 28, 2010

Hi Michael,

We are using FilteredBindingList and SortedBindingList on editable lists in our applications and they are not causing problems for us.

RockfordLhotka replied on Thursday, October 28, 2010

I don't see the issue. I took the sample you mention, and altered Root.cs as follows:

    public SortedBindingList<Child> Children
    {
      get { return new SortedBindingList<Child>(RealChildren); }
    }

    public static PropertyInfo<ChildList> RealChildrenProperty = RegisterProperty<ChildList>(p => p.RealChildren, RelationshipTypes.LazyLoad);
    public ChildList RealChildren
    {
      get
      {
        if (!FieldManager.FieldExists(RealChildrenProperty))
          LoadProperty<ChildList>(RealChildrenProperty, new ChildList());
        return GetProperty<ChildList>(RealChildrenProperty);
      }
    }

I just renamed Children to RealChildren, and created a new Children property that returns a SortedBindingList (yes, this is in 4.1, but these classes haven't changed since 3.8).

Michael replied on Monday, November 01, 2010

Thanks  for the replies.

I copied and pasted the above code into Root.cs, and updated the Form1_Load to child = root.RealChildren.AddNew(); as appropriate.

When I run it up, I click the childrenDataGridView Id column header twice, so that the data is sorted 4, 3, 2, 1, and click Apply. This throws an UndoException on line 294 of UndoableBase.cs.

Am I doing something wrong?

Kind regards
Michael

RockfordLhotka replied on Monday, November 01, 2010

I assume you are :)  But I don't know what - clearly there's something different between what you and I are doing.

Michael replied on Monday, November 01, 2010

OK, I've started from scratch. I can't see how I could be doing anything much different. This only takes a few minutes to set up:

  1. Download and extract RootChildGrandchildWinFormTest from netsamples 3.8.3
  2. Download and extract CSLA 3.8.3
  3. Include Csla.csproj in RootChildGrandchildWinFormTes.sln, reattach reference
  4. Build
  5. Edit Root.cs, replace Children property with RealChildren
  6. Add new SortedBindingList<Child> Children property
  7. Update DumpEditLevels() to var childList = ReadProperty<ChildList>(RealChildrenProperty);
  8. Update Form1.cs Form1_Load to child = root.RealChildren.AddNew(); in four places.
  9. Build
  10. Run
  11. Click childrenDataGridView Id column header (nothing happens, already sorted ascending. At this point, clicking Apply does not throw.)
  12. Click childrenDataGridView Id column header(sorts descending)
  13. Click Apply, UndoException thrown

I'm using Win 7 x64, but it fails on Win XP Pro x86 virtual machine also. I also tried 4.0.1 on Win 7 x64 and a Win 7 x86 virtual machine and exactly the same thing happened. Any clues?

Thanks for your help.
Michael

Michael replied on Thursday, November 04, 2010

Is anyone able to reproduce this or point me in the right direction?

I'm not new to CSLA, and as I said earlier, I first asked for help on this issue in November, 2008, then gave up when I couldn't find an answer.

I can upload the entire VS solution somewhere if that will help.

Kind regards
Michael

RockfordLhotka replied on Thursday, November 04, 2010

Sorry Michael, I'm really slammed at the moment and I don't have VS08 on my laptop. When I can catch my breath for a bit and have access to my desktop I'll try to reproduce the issue.

Or you can try and figure out what is different between the CSLA 3.8.3 and CSLA 4 SortedBindingList. The only possible thing I see is at revision 7511 where Jonny made a change to 4, and it isn't clear that was made (or needed to be made) in 3.8.

Since I can't replace the issue in CSLA 4 and .NET 4 there are really two options (I think)

  1. .NET 4 fixed a Windows Forms bug/issue
  2. CSLA 4 has something different in SBL (or BBLB)

 

Michael replied on Thursday, November 04, 2010

Thanks for the reply, Rocky. I'm not in a mad rush at this stage; I can just tell the client I'm still looking for answers. I want the right answer, so I'm happy enough to wait, as long as I know someone can look at it at some stage.

The problem is, I can't get it to work with 4.0.1 either; the same UndoException is thrown, as per my post a few days ago.

Thanks
Michael

RockfordLhotka replied on Thursday, November 04, 2010

I can try 4 quick enough, got nothing else to do while sitting on the plane :)

So here's what I did:

  1. Open RootChildGrandchildWinFormTest (4.1)
  2. Refactor-rename Root.Children to RealChildren
  3. Add new Children property as shown below
  4. Run app, interact with data, sort child grid, etc
  5. Click Cancel - all is good
  6. Click Apply - all is good

     public static PropertyInfo<SortedBindingList<Child>> ChildrenProperty = RegisterProperty<SortedBindingList<Child>>(c => c.Children);
    public SortedBindingList<Child> Children
    {
      get { return new SortedBindingList<Child>(RealChildren); }
    }

Obviously you and I are doing something different...

Michael replied on Thursday, November 04, 2010

Internet access on the plane, cool...

OK, I've just downloaded 4.1 and the samples and followed your steps.

Run it up, click childrenDataGridView Name column header once, and the data is sorted 3, 4, 1, 2. Click Cancel, the edit level report message box is shown, click OK and then the UndoException is thrown.

Restart and do the same thing, but this time click Apply, and the UndoException is thrown straight away (no edit level report shown).

It happens for me under Win 7 x64, Win 7 x86, and Win XP x86, with the debug and release bin files.

If I had more hair, I'd pull it out right now Tongue Tied

RockfordLhotka replied on Thursday, November 04, 2010

That turns out to be a good clue.

I was always entering at least 1-2 values before clicking apply or cancel. If you do that it works fine. It fails only if no values are edited.

This still doesn't give the full answer, but it is at least a start point. What's interesting is that the failure is in UndoableBase in the Child type, so it is in the child object, not the root or collection. This leads me to think that the current child isn't being properly unbound or something like that.

Have I mentioned recently how deeply and completely I hate Windows Forms data binding? And how amazingly happy XAML makes me, every time I use it (especially Silverlight)?

This is the sort of issue that can take many, many hours of meticulous debugging to solve. I can't promise when I'll next have that many hours to spend on this to be honest.

Michael replied on Thursday, November 04, 2010

I actually can't make it not fall over after a sort, no matter how many fields I edit. I'm glad I'm not taking crazy pills, though.

I share your hatred of Windows Forms data binding (perhaps not to the same degree), but I'm stuck with it just at the moment.

If you do get a chance to debug it, I'd be very grateful. Just keep me posted, if possible.

Thanks
Michael

Michael replied on Friday, November 12, 2010

Hi Rocky

I've looked a bit further into this issue, and what I've found is that the binding source's current item before an ApplySort() or ApplyFilter() does not have its EditLevel decremented appropriately, so when the unbind happens there's a mismatch. This looks pretty similar to the grandchild problem where we need to explicitly call EndEdit() on the grandchild when the children binding source's current item is changed.

I inherited FilteredBindingList and overrode (new) the ApplySort, RemoveSort, ApplyFilter and RemoveFilter methods and fired an OnSortChanging or OnFilterChanging event. In the screen I subscribe to this event and simply call EndEdit() on the binding source. This seems to be working.

Is there a better way or does this give you any clues?

Kind regards
Michael

menzel2911 replied on Friday, November 26, 2010

Hi Michael,

I run into a similar issue using Win Forms and 2 grids (master list, detail list) and I did the following (surprisingly it does work):

- whenever  the child item in the detail bindingsource does change, trigger an event and keep current child item from detail list in a local variable for later reference

- when current item in master list does change, call EndEdit on the memorized child item, so master list and child list stay in sync even with win form grids

I hope this does help

 

Sascha

 

Copyright (c) Marimer LLC