views:

43

answers:

4

I have a listbox on my form that looks like this:

<ListBox Name="lbResults" SelectionChanged="lbResults_SelectionChanged"/>

I am binding the following collection to it:

ObservableCollection<Hand> oHands = new ObservableCollection<Hand>();

using the following code:

lbResults.DataContext = oHands;
Binding binding = new Binding();
lbResults.SetBinding(ListBox.ItemsSourceProperty, binding);

The oHands collection gets populated via a background worker that announces via an event whenever a new Hand object is available. The ListBox refreshes perfectly when something is added. The ToString() result of the Hand object is displayed and that is what I want - so far so good. However, when the background worker finishes

void finder_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            oHands = new ObservableCollection<Hand>(oHands.OrderBy(o => o.PotSize));
            lbResults.SetBinding(ListBox.ItemsSourceProperty, new Binding());
        }

The items in the list are still showing up in the original order. I can confirm that the list is re-ordered but the items are still showing up in the original order. How do I refresh this binding?

A: 

You're really just supposed to inherit from the INotifyPropertyChanged interface, but heres another way to force an update to a binding:

BindingExpression exp = BindingOperations.GetBindingExpression(lbResults, Listbox.ItemsSourceProperty)
exp.UpdateTarget()

Edit: I also just noticed you aren't setting any binding in the XAML and appear to be doing it programmatically with an empty Binding. I haven't tried that way before, so see if changing your XAML to this might help:

<ListBox Name="lbResults" SelectionChanged="lbResults_SelectionChanged" ItemsSource="{Binding Path=oHands}"/>

Then you set lbResults.DataContext to point to the class that has the member oHands. This is what worked for me in my project (in IronPython, so forgive me if my examples didn't convert to C# perfectly).

Aphex
I updated my worker completed method to look like:void finder_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { oHands = new ObservableCollection<Hand>(oHands.OrderBy(o => o.PotSize)); BindingExpression exp = BindingOperations.GetBindingExpression(lbResults, ListBox.ItemsSourceProperty); exp.UpdateTarget(); }but it still doesn't show up in the new order :(
Ready Cent
I edited in another approach you can take.
Aphex
+1  A: 

instead of replacing the entire observable collection, you could just clear it and add all your new items. that wouldn't affect your binding.

You could also use a CollectionViewSource as your binding, and set the order on that instead of reordering the whole collection.

John Gardner
ok this worked but I think Alex answered with the same advice a moment earlier. thank you :)
Ready Cent
its ok, he needs the rep more than me for now :)
John Gardner
+1  A: 

you dont want to assign oHands a new collection. just Clear() the collection then add the results from the operation. don't update the binding

Alex Lo
A: 

Wouldn't it be a lot easier to just set the itemsource directly?

lbResults.ItemsSource = oHands;
mdm20
Would that actually update when oHands is changed or reordered?
Aphex
Since it's an observablecollection, changes to the collection would change the listbox. If you sort it and return a new collection, the itemsource will be updated with the new collection.
mdm20