Sometimes the simplest solution introduces a bug.
Let’s say there is a ListBox in WPF (or Silverlight) displaying bowlers* and their bowling scores:
<ListBox ItemsSource="{Binding Bowlers}" > <ListBox.ItemTemplate> <DataTemplate> <StackPanel Orientation="Horizontal"> <TextBlock Text="{Binding Name}"/> <TextBlock Text="{Binding Score}"/> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
Behind the scenes, a view model includes a Bowlers property for the binding to work.
public IEnumerable<Bowler> Bowlers { get { return _bowlers; } set { if (value != _bowlers) { _bowlers = value.ToObservable(); // ... Raise property changed event } } }
The property uses a ToObservable extension method that works in either Silverlight or WPF.
public static class ObservableExtensions { public static ObservableCollection<T> ToObservable<T>(this IEnumerable<T> items) { var collection = new ObservableCollection<T>(); foreach(var item in items) { collection.Add(item); } return collection; } }
So far everything is working. Bowlers appear on the screen, and as new bowlers get added to the collection …
_bowlers.Add(newBowler);
… they magically appear in the display.
Now someone wants the bowlers list sorted with the highest score appearing at the top of the list. Sounds like a simple change to the Bowlers property:
public IEnumerable<Bowler> Bowlers { get { return _bowlers.OrderByDescending(bowler => bowler.Score); } set { // same as before ... } }
At first glace, the new code works and the bowlers appear in sorted order, but something is wrong! What will break?
Hint:
Bowlers added with _bowlers.Add(…) never appear in the display. Why is that?
* Of the ten pin variety - not the spinning kind.