0

I have a problem with my code. I use a listbox and a observable collection to add the data to the list. the code looks like this:

ListData actualData;
ObservableCollection<ListData> data;

public Calculate()
{
    InitializeComponent();

    data = new ObservableCollection<ListData>();
    newData();

    listbox1.ItemsSource = data;
}

private void newData()
{
    actualData = new ListData("1", "2", "3");
    data.Add(actualData);
}

Now, I have a button which, for example, changes actualData but I cant see the change in the list.

the button looks like:

private void button1_Click(object sender, RoutedEventArgs e)
{
    actualData.first = "12";
}

I found a workaround:

listbox1.ItemsSource = null;
listbox1.ItemsSource = data;

but this is not a good solution, what is wrong here?

Ben
  • 51,770
  • 36
  • 127
  • 149
gurehbgui
  • 14,236
  • 32
  • 106
  • 178

2 Answers2

4

ObservableCollection will only notify when there is an activity on the list and not on the item of the list. Activity on list means adding/removing items in the list. You need to implement INotifyPropertyChange interface to ListData class to notify the changes in the ListData class properties/members.

ZafarYousafi
  • 8,640
  • 5
  • 33
  • 39
  • Also INotifyPropertyChanged works - I'm starting to wonder what the difference is...ah apparently something about it being removed in .NET - http://bytes.com/topic/c-sharp/answers/270938-ipropertychange – Charleh Jul 01 '12 at 11:24
  • Yeah I mean that but write IPRopretyChange by mistake. There is no such interface IPropertyChange :) – ZafarYousafi Jul 01 '12 at 11:25
  • No probs, you get +1 from me anyway :D – Charleh Jul 01 '12 at 11:45
3

As ZafarYousafi has correctly stated in his answer, ObservableCollection<T> will only notify the list of added and removed items; if you change a property on one of the items, it won't be updated in the list.

Instead, you need to change your ListData class's definition like so:

public class ListData : INotifyPropertyChanged

This requires your class to implement the PropertyChanged event:

public event PropertyChangedEventHandler PropertyChanged;

Now, all you need to do is change your definition of first (coding conventions dictate that properties should start with a capital letter, PascalCase):

private string first;
public string First
{
    get { return first; }
    set
    {
        first = value;
        var handler = PropertyChanged; //according to Essential C# (M. Michaelis) 
        if (handler != null)           //the copy should prevent threading issues
        {                              
            handler(this, new PropertyChangedEventArgs("First"));
        }
    }
}

By the way: I feel uncomfortable about having to pass in the property name as a string. For a more sophisticated solution, see this tutorial.

Adam
  • 15,537
  • 2
  • 42
  • 63
  • Spot on! The only thing I'd say is around the comments on the event invocation. This is absolutely best-practice and not really a disputed subject. See this answer: http://stackoverflow.com/questions/2582052/c-sharp-event-handlers-not-thread-safe – Alastair Pitts Jul 01 '12 at 11:43
  • okay; I was referring to [a blog post by Eric Lippert](http://blogs.msdn.com/b/ericlippert/archive/2009/04/29/events-and-races.aspx) – Adam Jul 01 '12 at 11:48