Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ListBox DataBound to ObservableCollection in Windows Phone MVVM doesnt update after Add

I have an ObservableCollection in the ViewModel that add new entries when an ApplicationBar button is pressed in the View. The ListBox which is bound to this ObservableCollection doesnt show the new/updated entry, it does show the items of the collection when the application loads. The ViewModel does implement INotifyPropertyChanged and I do call NotifyPropertyChanged when an item is added to the ObservableCollection (or) set.

ViewModel - based on what is read from the server, new items are added to the observable collection.

public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<SubsViewModel> _itemsUnread;
    public ObservableCollection<SubsViewModel> UnreadItems
    {
        get
        {
            return _itemsUnread;
        }
        set
        {
            _itemsUnread = value;
            NotifyPropertyChanged("Updated");
        }
    }

   void reader_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        switch (e.PropertyName)
        {
            case "Updated":

                Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        UnreadItems.Clear();

                        foreach (ItemViewModel subs in ItemsAll)
                        {
                                ....
                                UnreadItems.Add(subs);
                        }
                    }
                );

                IsDataUpdated = true;

                NotifyPropertyChanged(e.PropertyName);

                break;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(String propertyName)
    {
        if (null != this.PropertyChanged)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

view - sets the datacontext and itemsource

            <ListBox x:Name="SecondListBox" Margin="0,0,-12,0" ItemsSource="{Binding UnreadItems, Mode=TwoWay}">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Margin="0,0,0,7">
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding ItemTitle}" TextWrapping="NoWrap" Margin="12,0,0,0" Style="{StaticResource PhoneTextLargeStyle}"/>
...

    public MainPage()
    {
        _mainView = new MainViewModel();
        InitializeComponent();

        // Set the data context of the listbox control to the sample data
        DataContext = _mainView;
        this.Loaded += new RoutedEventHandler(MainPage_Loaded);
    }

Any Add/update to the observablecollection in the viewModel is not reflected in the listbox. i've read a bunch of places that notifypropertychanged is the solution, but i already have notifypropertychanged and still see the issue. Any ideas what i'm missing?

From @compoenet_tech's suggestion by adding the new item when the ApplicationBar buttin is pressed. I do see the listbox display the new item

SubsViewModel newitem = new SubsViewModel();
newitem.itemTitle = "test";
newitem.itemCount = test;
_itemssUnread.Add(newitem); test++;

So, doing the Add() outside the Dispatcher Invoke does work. But now the problem is that I get the new list from webservice using a callback, which is where i add the entries into unreaditems collection. which I cannot (??) do outside the dispatcher.

(web service) =callback=> ViewModel =observablecollection=> View

how does viewmodel get notified to update the collection outside a callback where i dont have to use dispather invoke? (or) use dispatcher invoke and not crash through cross thread reference.

Thanks

like image 884
VasiS Avatar asked Dec 01 '25 17:12

VasiS


2 Answers

  1. Please Instantiate the Observable collection before use. In constructor of the MainViewModel write the following code like

    public MainViewModel() { _itemsUnread = new ObservableCollection(); }

  2. Function reader_PropertyChanged is not required to implement.

  3. While calling the NotifyPropertyChanged use the Property Name as parameter like

    public ObservableCollection UnreadItems { get { return _itemsUnread; } set { _itemsUnread = value; NotifyPropertyChanged("UnreadItems"); } }

like image 100
Santhu Avatar answered Dec 03 '25 09:12

Santhu


A couple of notes:

1) According to MSDN, ObservableCollection already implements INotificatCollectionChanged for Silverlight, so you shouldn't have to reimplement it.

2) This code in the setter:

        NotifyPropertyChanged("Updated");

has some issues:

a) it will only be executed when the entire collection object itself is changed, not when items within the collection are changed.

b) If a is implemented as you want it to be, then the string parameter should be the property that changed to UnreadItems.

Update

I also suspect (noted in the comments below) that adding the items in the Invoke is causing the notification messages to be lost. I recommend changing the code to add the items directly rather than in the Invoke statement.

like image 41
competent_tech Avatar answered Dec 03 '25 11:12

competent_tech



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!