ObservableCollection - 无法更新UI

时间:2016-07-03 12:15:51

标签: c# wpf mvvm

我使用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>

如何看待我的网格包含两列具有以下绑定的网格:DateMinute。通过这种方式,我可以更新特定的项目细节。

这个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设置为静态,我可以看到添加的元素,但我还有其他非静态属性,这些都没有更新。

我做错了什么?感谢。

1 个答案:

答案 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。