Windows Phone MVVM中的ListBox DataBound到ObservableCollection在Add之后不会更新

时间:2011-12-20 22:20:00

标签: .net windows-phone-7 data-binding listbox observablecollection

我在ViewModel中有一个ObservableCollection,它在View中按下ApplicationBar按钮时添加新条目。绑定到此ObservableCollection的ListBox不显示新的/更新的条目,它确实在应用程序加载时显示集合的项目。 ViewModel实现了INotifyPropertyChanged,当一个项添加到ObservableCollection(或)集时,我确实调用了NotifyPropertyChanged。

ViewModel - 根据从服务器读取的内容,将新项目添加到可观察集合中。

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 - 设置datacontext和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);
    }

viewModel中对observablecollection的任何添加/更新都不会反映在列表框中。我已经阅读了很多地方,notifypropertychanged是解决方案,但我已经没有改变,仍然看到问题。我缺少什么想法?

来自@ compoenet_tech的建议 通过在按下ApplicationBar buttin时添加新项目。我确实看到列表框显示新项目

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

因此,在Dispatcher Invoke之外执行Add()确实有效。但现在问题是我使用回调从webservice获取新列表,这是我将条目添加到unreaditems集合的地方。我不能(??)在调度员之外做。

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

如何通知viewmodel在回调之外更新集合,我不必使用dispather调用? (或)使用调度程序调用而不是通过交叉线程引用崩溃。

由于

3 个答案:

答案 0 :(得分:2)

  1. 请在使用前实例化Observable集合。 在MainViewModel的构造函数中编写以下代码,如

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

  2. 无需执行函数reader_PropertyChanged

  3. 调用NotifyPropertyChanged时,请使用属性名称作为参数,如

    public ObservableCollection UnreadItems     {         得到         {             return _itemsUnread;         }         组         {             _itemsUnread = value;             NotifyPropertyChanged( “UnreadItems”);         }     }

答案 1 :(得分:1)

几点说明:

1)根据MSDN,ObservableCollection已经为Silverlight实现了INotificatCollectionChanged,所以你不必重新实现它。

2)这个代码在setter中:

        NotifyPropertyChanged("Updated");

有一些问题:

a)它只会在整个集合对象本身被更改时执行,而不是在集合中的项目发生更改时执行。

b)如果a按您希望的那样实现,那么string参数应该是更改为UnreadItems的属性。

<强>更新

我还怀疑(在下面的评论中注明),添加Invoke中的项目会导致通知消息丢失。我建议更改代码以直接添加项目,而不是在Invoke语句中。

答案 2 :(得分:0)

你的UnreadItems属性应该在

的构造函数中初始化

UnreadItems = new ObservableCollection();