Silverlight 2.0 beta 1 ListBox Databinding and possible bug ?

This week I’ve started playing with the new and longly waited Silverlight 2.0 beta 1 libraries. Finally we can develop real world bussiness applications with Silverlight using all the UI controls that this beta release includes.

After doing a couple of HelloWorld samples, I decided to try the DataBinding feature. In theory, it is really simple to databind our controls to the bussiness classes by setting their DataContext property which is something I won’t cover in this post and you can follow this link if you are looking for a nice tutorial on this topic.

What I’ll cover here is a strange issue I found when trying to databind a ListBox control to a simple List<string> data source.

In my XAML code, I’ve simply added a ListBox control and set it’s DataContext property to the databinding I’ll be using:

<ListBox x:Name=”Items” ItemsSource=”{Binding Items, Mode=OneWay}” />

I also set the DataContext property of the list to the object I’ll be using to do the databinding at the codebehind of the control, there’s also a button that will call the AddItem function (see later) of my bussiness class:

public partial class Page : UserControl
{
    private Invoice _invoice = new Invoice();    

    public Page()
    {
        Items.DataContext = _invoice;
        myButton.Click += new RoutedEventHandler(myButton_Click);
    }

    void myButton_Click(object sender, RoutedEventArgs e)
    {
        _invoice.AddItem("this is a new Item!");
    }
}

And here is my business class which I’ve reduced to the list property to keep things simple:

public class Invoice : INotifyPropertyChanged
{
    private List _items = new List();

    public List Items
    {
        get { return _items; }
        set { _items = value; NotifyPropertyChanges("Items"); }
    }

    public void AddItem(string newItem)
    {
        _items.Add(newItem);
        NotifyPropertyChanges("Items");
    }

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    public void NotifyPropertyChanges(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

The interesting part in the above code is the AddItem function. Since I wan’t to be able to add new items in the Items collection and automatically update the UI control responsible for displaying the list of items, I can’t simply call the Items.Add method because we must call NotifyPropertyChanges to get our databinding updated. We could also have created our custom list class that implemented INotifyPropertyChanged interface and took care of this (which is something I will surely do in my applications) but for this example is not necessary.What one would expect to happen with this code is that whenever the button click event is clicked, a new item is added in the “Items” list and the ListBox is updated. However, this is not working this way. What happens is that the item is added in the “Items” list but the ListBox control is not updated, the new item is not showing in the UI at all, futhermore, if we set up some breakpoints right after the AddItem method is called, we will see that the ItemsSource collection of the ListBox control is correctly updated and will contain a new item as it should, but the control is not updating it’s UI.

Finally, if I change the AddItem method of the bussiness class to the following implementation, everything works as expected and the list UI is correctly updated:

public void AddItem(string newItem)
{
    List temp = new List(_items);
    temp.Add(newItem);
    _items = new List(temp);
    NotifyPropertyChanges("ITems");
}

I haven’t still found an explanation of this strange behaviour and would really appreciate if somebody could point me out if there is something I have done wrong or if it’s some kind of bug in the beta 1 library. So any comment regarding this will be appreciated !Thanks for your time and come back again for more interesting topics on the highly expected Silverlight 2.0 release !

Advertisements

7 Responses to Silverlight 2.0 beta 1 ListBox Databinding and possible bug ?

  1. oricode says:

    I forgot to mention that you can also use a ObservableCollection item instead of a List one, with this approach, you don’t have even to implement INotifyPropertyChanged interface and the collection takes care of everything.

    However, I couldn’t use this approach because I already had the bussiness classes implemented by a third party developer and they used List classes !

  2. Ash says:

    Hi, just one thought on your problem.

    Listboxes have 2 input modes, itemssource and the std add / remove etc.

    According to this link (http://www.drwpf.com/blog/Home/tabid/36/EntryID/18/Default.aspx) you can’t use the itemsource and items properties together, you can only use one of the other as they each use a different mode and each is mutually exclusive.

  3. oricode says:

    Hi, thx for your comment !

    Actually I’m only using indirect binding with the ItemSource property at the ListBox control and then, setting it’s DataContext property at the load event to my List object so there should be no problem with that. At any point I’m using ListBox items collection directly.

    I’m doing exactly what the link you provided says when talking about observable listboxes, that is, provide my own implementation of INotifyPropertyChanged and raise the event when an item is added (always at the List object, not the ListBox control)

  4. Dharmesh Surti says:

    Hi,

    The reason is ListBox control in silverlight is not a two way databinding control. That is, based on ur example when u make change in List object it will not effect the ListBox control. When u do databinging in ASP.Net, we actually call method databind after providing the datasource. There is no such concept in windows. We just provide itemsource. So, what itemsource check whether the provider object is same or not. If its same then it will not bind it again.
    Same thing happen here in ur case. In first case u declare the List object as global for the page and adding the content in it and in second case u r creating a new list object everytime u add new item.
    If u want to implement same funcitionality based on ur first case then u have to implement observable collection object. For more information u can go through the link below:
    http://silverlight.net/learn/tutorials/databinding.aspx

    hope this will help u understanding the problem.

  5. Mario Di Vece says:

    I’ve experienced the same behavior… It’s most likely a bug. But here’s how you get around it. (A little dirty but ehh… it works) –

    // the list object changes here….

    this.FilesListBox.SelectedIndex = -1;
    var source = this.FilesListBox.ItemsSource; // save a reference to the original source
    this.FilesListBox.ItemsSource = null; // unset the source
    this.FilesListBox.UpdateLayout();
    this.FilesListBox.ItemsSource = source; // set the source to the original one

  6. Sage says:

    For OneWay binding to work, the ItemSource has to implement the INotifyCollectionChanged interface. I’d recommend using an ObservableCollection instead of a List, since ObservableCollection implements INotifyCollectionChanged.

  7. oricode says:

    Yep, I had already noticed that on my first comment on this post. The problem rises when dealing with existing business classes out of your control that are using List objects !

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: