BUG: Items are sorted correctly sometimes, other times not so much.
FREQUENCY: Intermittent, never when debugging and stepping through everything, always seems to happen when I'm not.
RATING: Probably the most painful bug I've worked on in some time.
So I've got an ItemsControl in a custom XAML user control. All this does is display an IEnumerable<T> of video items. Simple. To provide a better user experience we implemented an ObservableCollection<T> as the source of the ItemsControl with a Collection_Changed event so we can add one item at a time to the collection so as to not wait for the entire collection to populate before displaying to the user. Now we're able to display the first 2 items and the scrollbar height shrinks as items are being added. It's a nice user-experience.
Anyway, so for the implementation. When the VideoRetrieveComplete event fires (after making a web service request for the data) we call the UpdateVideoCollection method.
UIThread.Run(delegate
{
videoListControl.UpdateVideos(args.VideoItems);
videoListControl.itemsControlVideoListing.DataContext = new VideoItem();
}
Notice that we're doing this in the UI Thread. The code above is located in our Controller class. The args.VideoItems is an IEnumerable<VideoItem> and they are sorted in the order they need to be in. I have verified this time and time again with painful debugging.
Now time for VideoList controls properties, objects, and methods:
public int CurrentPageIndex { get; set; }
public ObservableCollection<VideoItem> ObservableCollection { get; set; }
private List<VideoItem> VideoItems = new List<VideoItem>();
Constructor where everything is initialized. Probably important to include this.
public VideoList()
{
CurrentPageIndex = 0;
InitializeComponent();
ObservableCollection = new ObservableCollection<VideoItem>();
itemsControlVideoListing.ItemsSource = ObservableCollection;
ObservableCollection.CollectionChanged += CollectionChanged;
}
public void UpdateVideos(List<VideoItem> videoItems)
{
UIThread.Run(delegate
{
VideoItems.AddRange(videoItems);
ObservableCollection.Clear();
if (VideoItems != null && VideoItems.Count > 0)
{
VideoItem videoItem = VideoItems[0];
VideoItems.RemoveAt(0);
ObservableCollection.Add(videoItem);
}
});
}
void CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (VideoItems.Count > 0)
UIThread.Run(delegate
{
VideoItem videoItem = VideoItems[0];
VideoItems.RemoveAt(0);
ObservableCollection.Add(videoItem);
});
}
The reason for removing an item, and then re-adding it is that this is the only way we can get our Converters to fire off, otherwise the collection hasn't changed and UI elements don't update. For example, switching between tabs the user can add videos to their playlist. Each time the tabs are selected and the VideoListing populates the VideoItems within that listing needs to show either an ADD / DELETE FROM PLAYLIST button depending on whether or not the item is in the playlist. If there's another way to get those Converters to fire off I'm all ears.
So the problem is that more often than not the videos, which come in sorted correctly, are not always displayed that way. For example, if I have 5 videos with dates 10/1/2008, 10/1/2008, 9/30/2008, 9/29/2008, 9/28/2008 sometimes the sort will be:
10/1/2008
9/30/2008
9/29/2008
9/28/2008
10/1/2008
or:
9/30/2008
9/29/2008
10/1/2008
9/28/2008
10/1/2008
You get the idea. Could it be that we are not implementing this correctly? Do we need to rebind the ItemsControl or is this correct?
I've been working on this bug for a day and a half now and have nothing. I'm sure it's probably something stupid.
I'm all ears if you have anything. ANYTHING!
Oh, should probably add that if I page to the next listing of videos and then back it'll remedy itself!
[166010]







