更新添加项目的UI更改为集合

时间:2014-03-16 14:28:48

标签: c# wpf windows xaml

我使用的ObservableCollection后来应该填充来自COM端口的数据,这意味着它会更新很多。出于测试目的,我设置了设计时样本数据(工作正常)和运行时样本数据,但是在向我的集合中添加项目时,我无法更新UI。我已经设法在我的课堂上成功实现了INotifyPropertyChanged,如下所示:

public class SensorViewModel : INotifyPropertyChanged
{
    public SensorViewModel()
    {
        dataItems = new ObservableCollection<SensorData>();
        dataItems.CollectionChanged += dataItems_CollectionChanged;
    }

    private ObservableCollection<SensorData> _dataItems;
    public ObservableCollection<SensorData> dataItems
    {
        get { return _dataItems; }
        set
        {
            _dataItems = value;
            // notify of changes
            NotifyPropertyChanged("dataItems");
            NotifyPropertyChanged("lastItem");
        }
    }

    public SensorData lastItem
    {
        get { return dataItems.Last(); }
    }

    public void LoadData()
    {
        dataItems.Add(new SensorData { id = 0, accelX = 0.231, accelY = 0.345, accelZ = -1.234 });
        dataItems.Add(new SensorData { id = 1, accelX = 1.231, accelY = 1.345, accelZ = -0.234 });
    }

    // handle property changes
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged(string propertyName)
    {
        var handler = this.PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propertyName));
    }

    void dataItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        // get the sender observable collection
        ObservableCollection<string> obsSender = sender as ObservableCollection<string>;

        List<SensorData> editedOrRemovedItems = new List<SensorData>();

        if (e.NewItems != null)
        {
            foreach (SensorData newItem in e.NewItems)
            {
                editedOrRemovedItems.Add(newItem);
            }
        }

        if (e.OldItems != null)
        {
            foreach (SensorData oldItem in e.OldItems)
            {
                editedOrRemovedItems.Add(oldItem);
            }
        }

        // get the action which raised the collection changed event
        NotifyCollectionChangedAction action = e.Action;
    }
}

我在MainWindow.xaml.cs上创建DataContext,然后调用LoadData()。但是在我的单独页面上,名为AccelData.xaml(使用ModernUI WPF项目的子标签),绑定不会更新。我将其与{Binding lastItem.accelX}绑定。

我是否需要以某种方式将DataContext从MainWindow复制到子页面,或者我只是不使用CollectionChanged事件?我似乎无法将我的绑定值显示在运行时。

2 个答案:

答案 0 :(得分:2)

您明确需要PropertyChanged 举起lastItem个活动,以防您希望在UI上刷新它。

从collectionChanged handler:

执行
void dataItems_CollectionChanged(object sender, 
                                 NotifyCollectionChangedEventArgs e)
{
   ......
   NotifyPropertyChanged("lastItem");
}

你的collectionChanged处理程序对我没有任何意义。在列表中添加项目而不在任何地方使用它。

此外 obsSender将始终为空,因为发件人集合的类型为ObservableCollection<SensorData>,但您将其类型转换为ObservableCollection<string>

// get the sender observable collection (THIS WILL BE NULL ALWAYS)
ObservableCollection<string> obsSender = sender as ObservableCollection<string>;

答案 1 :(得分:1)

三件事:

  1. 我不明白你在CollectionChanged事件中做了什么。您正在创建列表并将项目分配给该列表,然后不执行任何操作以使列表丢失。这是你的意图吗?

  2. 我认为你应该改变你的绑定。而不是{Binding Path = lasItem.accelX}做类似的事情:DataContext = {Binding lastItem} Property(例如Text)= {Binding accelX}。

  3. 我认为您的代码存在另一个可能的错误:

    dataItems.CollectionChanged + = dataItems_CollectionChanged;

  4. 您只分配一次事件处理程序。当您更改ObservableCollection(由于公共setter而可能)时,您应该从旧对象中删除事件处理程序并将事件处理程序添加到新对象。 类似的东西:

    private ObservableCollection<SensorData> _dataItems;
    public ObservableCollection<SensorData> dataItems
    {
          get { return _dataItems; }
          set
          {
              if(_dataItems != null ) _dataItems.CollectionChanged -= dataItems_CollectionChanged;
              _dataItems = value;
              if(_dataItems != null ) _dataItems.CollectionChanged += dataItems_CollectionChanged;
              // notify of changes
              NotifyPropertyChanged("dataItems");
              NotifyPropertyChanged("lastItem");
          }
     }