我使用ObservableCollection时出现问题,特别是当我向其添加项目时,UI不会更新网格。在详细解释之前,我想向您展示感兴趣的xaml结构:
<ListView ItemsSource="{Binding Playing}">
<ListView.View>
<GridView>
<GridViewColumn Header="Data" Width="150" DisplayMemberBinding="{Binding Path=Date}"/>
<GridViewColumn Header="Minuto" Width="70" DisplayMemberBinding="{Binding Path=Minutes}"/>
</GridView>
</ListView.View>
</ListView>
如何看待我的网格包含两列具有以下绑定的网格:Date
和Minute
。通过这种方式,我可以更新特定的项目细节。
这个Grid是我的MainWindow.xaml的一部分,在我设置datacontext的顶部是这样的:
xmlns:VM="clr-namespace:Live.Resources.UI.ViewModels"
和
<Window.DataContext>
<VM:LiveViewModel />
</Window.DataContext>
在我的LiveViewModel中我已经定义了这个类:
public partial class LiveViewModel : ViewModel
{
private ObservableCollection<Models.Playing> _playing = new ObservableCollection<Models.Playing>();
public ObservableCollection<Models.Playing> Playing
{
get { return _playing; }
}
...
该类扩展了在INotifyPropertyChanged实现中的基本ViewModel,只是为了完整性:
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
现在我的ObservableCollection基于具有此定义的播放模型:
public class Playing : ViewModel
{
private string _dateTime;
private string _minutes;
public string Date
{
get { return _dateTime; }
set { SetField(ref _dateTime, value); }
}
public string Minutes
{
get { return _minutes; }
set { SetField(ref _minutes, value); }
}
...
这个类也实现了INotifyPropertyChanged。
所以当我在我的收藏中添加一个项目时,我做了这个(在我的MainWindow.xaml中):
LiveViewModel lsVm = new LiveViewModel();
var playingCollection = lsVm.Playing;
playingCollection.Insert(0, new Playing
{
Date = "03/07/2016",
Minutes = "5",
Home = "foo",
});
遗憾的是,在网格中我看不到任何添加的元素。 如果我创建一个静态集合,则不会发生这种情况,事实上,如果我将ObservableCollection设置为静态,我可以看到添加的元素,但我还有其他非静态属性,这些都没有更新。
我做错了什么?感谢。
答案 0 :(得分:1)
原因是您获得此行为的原因是因为lsVm
的{{1}}实例与LiveViewModel
的{{1}}中的实例不同
这里发生了什么 - 创建窗口后,它会创建DataContext
的实例并设置MainWindow
,因为您提供了这些代码行
LiveViewModel
如果您要从DataContext
的代码隐藏中修改集合,则有以下方法可以解决此问题:
1您需要使用<Window.DataContext>
<VM:LiveViewModel />
</Window.DataContext>
访问MainWindow.xaml
,因此您可能会看起来像这样:
ViewModel
2从代码隐藏中创建DataContext
的实例后,您需要使用此实例设置var lsVm = this.DataContext as LiveViewModel;
if (lsVm != null)
{
var playingCollection = lsVm.Playing;
playingCollection.Insert(0, new Playing
{
Date = "03/07/2016",
Minutes = "5",
Home = "foo",
});
}
:
LiveViewModel
<强> UPD 强> 此外,如果您使用第二种方法,则不需要从XAML代码设置DataContext。