【问题标题】:ListBox DataBound to ObservableCollection in Windows Phone MVVM doesnt update after Add列表框数据绑定到 Windows Phone MVVM 中的 ObservableCollection 添加后不更新
【发布时间】:2012-01-24 20:17:45
【问题描述】:

我在 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 是解决方案,但我已经 notifypropertychanged 并且仍然看到问题。任何想法我错过了什么?

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

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

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

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

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

谢谢

【问题讨论】:

  • 在您的 UnreadItems 属性设置器中,您为“更新”命名属性提出了 NotifyPropertyChanged,您应该为 UnreadItems 提出它。至少我认为这是问题所在。
  • 我现在明白你为什么用 Update 调用它了,也许这是你处理属性更改事件的问题,所以它没有到达 UI。

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


【解决方案1】:
  1. 请在使用前实例化 Observable 集合。 在MainViewModel 的构造函数中编写如下代码,如

    公共 MainViewModel() { _itemsUnread = new ObservableCollection(); }

  2. 函数reader_PropertyChanged不需要实现。

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

    public ObservableCollection UnreadItems { 得到 { 返回_itemsUnread; } 放 { _itemsUnread = 值; NotifyPropertyChanged("UnreadItems"); } }

【讨论】:

  • 1.是的,collection 的初始化方式相同 2. reader_PropertyChanged 是来自 WebService 的回调,用于获取新的项目列表。
  • 在我看来,请同时执行第三步并尝试。
【解决方案2】:

几点说明:

1) 根据MSDN,ObservableCollection 已经为 Silverlight 实现了 INotificatCollectionChanged,因此您不必重新实现它。

2) setter 中的这段代码:

        NotifyPropertyChanged("Updated");

有一些问题:

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

b) 如果 a 按照您的意愿实现,则字符串参数应该是更改为 UnreadItems 的属性。

更新

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

【讨论】:

  • 是的,以上两点我都明白了。他们被添加来尝试是否解决了问题,但它没有。我在设置 unreadItems 时添加了 NotifyPropertychanged,以防我为它分配一个新集合。但这里不是这样。
  • ^^ 我的意思是,如果没有我明确调用 NotifyPropertyChanged("") ,它就无法工作。
  • @VasiS:好的。您是否已验证这些项目实际上已添加到基础集合中?另外,您是否尝试过将项目直接添加到集合中而不是通过调用(我想知道属性更改通知是否在某处被吞没了)?
  • 是的,unreadItems 集合中确实包含更新的和新的项目。
  • 你是对的,通过在 ApplicationBar 按钮被按下时添加新项目。我确实看到列表框显示了新项目SubsViewModel newitem = new SubsViewModel(); newitem.itemTitle = "test"; newitem.itemCount = test; _itemssUnread.Add(newitem); test++;
【解决方案3】:

你的 UnreadItems 属性应该在构造函数中初始化为

UnreadItems = new ObservableCollection();

【讨论】:

  • 他说他在一开始就看到了原始值,所以他已经在他的代码的其他地方做了这个。
  • 是的,它是在MainViewModel的构造函数中初始化的。我这里没有复制代码。
猜你喜欢
  • 2012-03-09
  • 1970-01-01
  • 2012-03-18
  • 2011-08-16
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2012-09-11
相关资源
最近更新 更多