我使用的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事件?我似乎无法将我的绑定值显示在运行时。
答案 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)
三件事:
我不明白你在CollectionChanged事件中做了什么。您正在创建列表并将项目分配给该列表,然后不执行任何操作以使列表丢失。这是你的意图吗?
我认为你应该改变你的绑定。而不是{Binding Path = lasItem.accelX}做类似的事情:DataContext = {Binding lastItem} Property(例如Text)= {Binding accelX}。
我认为您的代码存在另一个可能的错误:
dataItems.CollectionChanged + = dataItems_CollectionChanged;
您只分配一次事件处理程序。当您更改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");
}
}