Solving the ObservableCollection bug on Windows 8

If you tried to build applications for Windows 8 with XAML/C#, you may have noticed an annoying issue: If you have a list controls (for example a GridView) and you bind the ItemsSource property to a property of type ObservableCollection<Something> on your ViewModel, the GridView is not updated when the collection’s content changes. The CollectionChanged event is raised properly, but it is not honored by the binding system.

Thankfully, this is a temporary bug, and it should be solved in the Consumer Preview version of Windows 8, due for release end of February. In the meantime, however, it is easy to circumvent this bug.

To find a solution, I researched the web and found a class named ObservableVector, for which changes are honored by the binding system. However this class had a major flaw: it forces the original ObservableCollection to be <object> instead of being strongly typed. This is of course super annoying when you are trying to share code with Silverlight/WPF/Windows Phone. So I took a good look at it, and I came up with what I think is a better implementation.

With this implementation, the original ObservableCollection can remain untouched. For instance, if you have this in the original, shared MainViewModel.cs file:

public partial class MainViewModel : ViewModelBase
{
    public ObservableCollection<UploadFileInfoViewModel> Files
    {
        get;
        set;
    }

    // ...
}

Notice that the MainViewModel class is partial. This allows easily adding the following code only into the Win8 project, into another file added only to the Win8 project, named MainViewModel.Win8.cs:

public partial class MainViewModel
{
    private ObservableVector<object, UploadFileInfoViewModel> _filesWin8;
    public ObservableVector<object, UploadFileInfoViewModel> FilesWin8
    {
        get
        {
            if (_filesWin8 == null)
            {
                Files.CollectionChanged += (s, e) =>
                {
                    if (e.NewItems != null)
                    {
                        foreach (var file in e.NewItems)
                        {
                            FilesWin8.Add(file);
                        }
                    }

                    if (e.OldItems != null)
                    {
                        foreach (var file in e.OldItems)
                        {
                            FilesWin8.Remove(file);
                        }
                    }
                };

                _filesWin8 = Files.ToObservableVector<object, UploadFileInfoViewModel>();
            }

            return _filesWin8;
        }
    }
}

This adds a new property to the MainViewModel class, which observes the old property’s CollectionChanged event. This way, by binding the GridView’s ItemsSource property to FilesWin8 instead of Files, your UI will react properly to the event.

Hopefully this little trick will help the readers while waiting for the Consumer Preview!

Cheers,
Laurent

 

Print | posted on Sunday, February 19, 2012 6:11 PM

Feedback

# re: Solving the ObservableCollection bug on Windows 8

left by David Barrows at 8/2/2012 5:39 PM Gravatar
Hi Laurent,
I've seen a number of blog posts like this, which talk about how it's an issue in the early versions (i.e. the consumer preview etc); your post suggests it would be fixed by the end of February. My question is, has it been fixed yet? Is it now (as of August 2012) possible to write XAML that binds to a strongly typed ObservableCollection<T> ? Thank you, -Dave

# re: Solving the ObservableCollection bug on Windows 8

left by Laurent at 8/2/2012 6:06 PM Gravatar
Hi,

Yes absolutely, this bug has been fixed I think in Win8 CP already.

Cheers,
Laurent
Post A Comment
Title:
Name:
Email:
Website:
Comment:
Verification: