2

I have ObservableCollection that contains a custom object. Normally the items get added at the end of the list

What i am looking for:

  • Items being added from the beginning of the list.
  • This may only show in the UI, my entire program is already using the positions of data inside this list. So the objects inside it may not change order in the code behind.

This ObservableColection holds Button objects (custom styled). These buttons are being displayed in a ListBox and inside a StackPanel with Horizontal layout (so the buttons get nicely placed after each other).

Problem:

Every button that gets created receives a DateTime. A newly added button always has a more recent date then the button before that. All the calculations for this are happening inside a timer(currently running every second).

So i am basically sorting on this time, but after like 3 buttons suddenly a button gets placed at right hand side (instead of the left hand side).

For example:

Btn3: 14:15:45(correct) Btn4: 14:16:00(wrong) Btn2: 14:15:32(correct) Btn1: 14:04:17(correct)

The first 3 buttons get added properly at the beginning of the list each time. And suddenly the fourth item is being added at the second place. It seems it is not always comparing the time? Every time a button gets created the CollectionViewSource method gets called upon.

Is there something wrong with the CollectionViewSource or is there a better way of handling this?

PeterP
  • 741
  • 1
  • 8
  • 20
  • Are you trying to sort in asc or desc order of time? – Siva Gopal May 02 '12 at 12:20
  • Descending as shown in the code example. But it does not gives stable results. First it adds in the proper order then after 3 buttons its started adding items totally wrong. – PeterP May 02 '12 at 12:23
  • 1
    Have a look at the problem : http://stackoverflow.com/questions/3610438/collectionviewsource-sorting-only-the-first-time-it-is-bound-to-a-source – Siva Gopal May 02 '12 at 12:29
  • How about trying to do use `Insert()` method instead of `Add()` and add new item at index 0? – StaWho May 02 '12 at 12:31
  • I cannot do that since my calculations depend on the order of the items (placed in bold in my question). – PeterP May 02 '12 at 12:38

4 Answers4

4

For grins would you try the sort in XAML? I know these are not the same names but this is from working code. I am not sorting on date but I have done hundreds of adds and removes from DocProps and the sort does not break.

        <ListBox.DataContext>
            <CollectionViewSource Source="{Binding Path=DocProps}">
                <CollectionViewSource.SortDescriptions>
                    <scm:SortDescription PropertyName="Date" Direction="Desc" />
                </CollectionViewSource.SortDescriptions>
            </CollectionViewSource>
        </ListBox.DataContext>

My other thought is that it may be sorting a string representation of date and getting it wrong. Maybe create an index 001 - 00n to sort on.

I added a date to this collection and it worked from me. But had to make the date a sortable format.

     Text="{Binding Path=Date, Mode=OneWay, StringFormat={}{0:s}}"
paparazzo
  • 44,497
  • 23
  • 105
  • 176
  • Care to elaborate a little but further what you mean with the index? Will look into trying it in xaml thanks. I also tried sorting on title. Because everybody button that gets created gets a unique title (btn1, 2, 3 etc). Even while sorting on that i could not get the proper sorting order. Regards. – PeterP May 02 '12 at 13:15
  • The xaml does not seem to work, it just adds to the right with no sorting happening at all. – PeterP May 02 '12 at 13:32
  • 1
    See update to answer. All I can say is that it works for me. If sort is not working at all for you then I think think you need to break it down to a simple ListBox of text to sort and start adding in changes to see where it breaks. – paparazzo May 02 '12 at 13:48
  • I just have no idea. It works for me on a fairly complex page. Like I said break it down. I am using this on an object and it is working. It is not a Button but that should not break it. Is Date Get being called? And I think mine was working before the StringFormat={}{0:s} but it was hard to see. – paparazzo May 02 '12 at 14:06
  • Made it work with making the Title a unique integer Value, not really sure why my date was not sort able to begin with. Btw where would you place that Text? Thanks. – PeterP May 02 '12 at 14:07
  • I don't think you have to place it. I took Date out of the ListView UI and it still sorts fro me. – paparazzo May 02 '12 at 14:12
0

If I understood well, I would use the Ticks property of DateTime to sort because it is very accurate by its nature and of cource is a simple number.

Dummy01
  • 1,985
  • 1
  • 16
  • 21
0

does your ICollectionView is an instance field or a local variable like in your codesnippet?

it has to be an instance field, then you sorting will work. btw i tried your snippet and changed the icollectionview to a field and it works.

blindmeis
  • 22,175
  • 7
  • 55
  • 74
0

If you follow the link Siva posted in the comments and follow another link from there, you'll eventually end up at http://connect.microsoft.com/VisualStudio/feedback/details/592897/collectionviewsource-sorting-only-the-first-time-it-is-bound-to-a-source where somebody posted a workaround. This workaround is written for DataGrid but you can tweak it for whatever control you happen to be using:

Posted by Greg Bachraty on 2/28/2011 at 6:50 AM

Implement your own DataGrid:

public class SDataGrid : DataGrid
{
    static SDataGrid()
    {
        ItemsControl.ItemsSourceProperty.OverrideMetadata(typeof(SDataGrid), new FrameworkPropertyMetadata((PropertyChangedCallback)null, (CoerceValueCallback)null));
    }
}

The only thing coerce callback does in the current implementation is clear the sort descriptions. You can simply "cut" this code by overriding metadata. Not viable on Silverlight: OverrideMetadata API is not public. Though I'm not sure Silverlight is affected by this bug. Other risks and side effects may apply.

Robert Levy
  • 28,747
  • 6
  • 62
  • 94