0

I am working on a scheduling program in which items have a scheduled date, but the user can elect to override this for a date they choose. To implement this, my Item object uses two properties: ScheduledDate (DateTime) and ActualDate (DateTime?). Therefore, if the ActualDate property is null, the user has not overridden the schedule for this item.

In one of my views, I need to display these items in a ListBox, sorted by the actual date. The trouble I am having is how to implement a CollectionViewSource with these two properties.

I know it's not correct, but I need something like this:

<CollectionViewSource x:Key="TransactionsViewSource"
                      Source="{Binding ElementName=ThisControl, 
                                       Path=Items}">
    <CollectionViewSource.SortDescriptions>
        <cm:SortDescription PropertyName="ActualDate ?? ScheduledDate"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

(ThisControl is the name of the UserControl that hosts the ListBox.)

If I add a second SortDescriptor (like below), I get a list sorted by ActualDate, then by Scheduled Date, which groups all of the overridden items together. This is not the desired behavior.

<CollectionViewSource x:Key="TransactionsViewSource"
                      Source="{Binding ElementName=ThisControl, 
                                       Path=Items}">
    <CollectionViewSource.SortDescriptions>
        <cm:SortDescription PropertyName="ActualDate"/>
        <cm:SortDescription PropertyName="ScheduledDate"/>
    </CollectionViewSource.SortDescriptions>
</CollectionViewSource>

Thanks.

H.B.
  • 166,899
  • 29
  • 327
  • 400
gregsdennis
  • 7,218
  • 3
  • 38
  • 71

2 Answers2

1

I ended up creating a new method in my UserControl class that used LINQ to keep the underlying ObservableCollection sorted. I then called this method whenever an item was edited (actual date overridden) or if a new item was added. Finally, I removed the CollectionViewSource from the XAML and bound the ListBox to the Items property (which I already had as a dependency property). The result looks like this:

XAML:

<ListBox ItemsSource="{Binding ElementName=ThisControl,
                               Path=Items}"/>

C#:

public static readonly DependencyProperty ItemsProperty =
    DependencyProperty.Register("Items",
                                typeof(ObservableCollection<MyItem>),
                                typeof(MyControl),
                                new UIPropertyMetadata(null));

public ObservableCollection<MyItem> Items
{
    get { return (ObservableCollection<MyItem>) GetValue(ItemsProperty); }
    set { SetValue(ItemsProperty, value); }
}

private void SortItems()
{
    Items = new ObservableCollection<MyItem>(Items.OrderBy(i => i.ActualDate ??
                                                                i.ScheduledDate));
}

Then I just use SortItems() anywhere that the items in the collection or the collection itself changes.

It works perfectly, and I didn't have to create and manage a new property. I can live with the little bit of overhead that LINQ creates.

gregsdennis
  • 7,218
  • 3
  • 38
  • 71
0

I think the easiest way would be to create one more property for the sorting:

public DateTime SortingDate
{
    get { return ActualDate ?? ScheduledDate; }
}

.

<CollectionViewSource.SortDescriptions>
    <cm:SortDescription PropertyName="SortingDate"/>
</CollectionViewSource.SortDescriptions>
LPL
  • 16,827
  • 6
  • 51
  • 95
  • How do I handle property changes? What if the user changes the actual date of one of the items? I'd prefer not to have to manage another property just for sorting. – gregsdennis Jun 12 '12 at 02:50
  • That's easy. If you notify for ActualDate or ScheduledDate change just notify for SortingDate too. The only problem could be the dynamically update of view. For that I always suggest reading this article from Dr. WPF: [ItemsControl: 'E' is for Editable Collection](http://drwpf.com/blog/2008/10/20/itemscontrol-e-is-for-editable-collection/). – LPL Jun 12 '12 at 12:37
  • Nice link! I may end up implementing that to solve some other problems I'm having as well. – gregsdennis Jun 13 '12 at 16:09