【问题标题】:How to Refresh a ListItem in WPF ListView ,CollectionViewSource in MVVM如何刷新 WPF ListView 中的 ListItem ,MVVM 中的CollectionViewSource
【发布时间】:2010-07-21 17:46:32
【问题描述】:

我有一个 ObservableCollection 分配给 People 并有一个 PersonViewModel 和 PeopleViewModel

_people = GetAll().ToList();
List<PersonViewModel> allPeople = (from person in _people 
                                   select new PersonViewModel(person)).ToList();
AllPeople = new ObservableCollection<WorkOrderListItemViewModel>(allOrders);
AllPeopleCollection.Source = AllPeople;

其中
AllPeopleCollection 是 CollectionViewSource 类型的公共属性,
AllPeople 是 ObservableCollection 类型的公共属性

单击该项目时,我需要更改用于列表视图中一行的图标。 但是要更新视图,我需要再次阅读整个列表。由于我的列表有 100 多条记录,因此刷新列表需要很长时间。

有没有办法我只能刷新列表中的特定项目并在 UI 上刷新它。

【问题讨论】:

  • 我相信如果你的项目本身实现了 INotifyPropertyChanged,这应该可以解决它。

标签: c# wpf listview mvvm


【解决方案1】:

是的,您的 PersonViewModel 应该实现 INotifyPropertyChanged 并在图标属性的设置器中引发 PropertyChanged 事件(因此每次更新后都会自动引发)。如果您的绑定正确,这将触发 GUI 刷新。

代码:

public class PersonViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private YourIconType _Icon;
    public YourIconType Icon
    {
        get { return _Icon; }
        set
        {
            _Icon = value;
            if (PropertyChanged != null)
                PropertyChanged.Invoke(this, 
                    new PropertyChangedEventArgs("Icon"));
        }
    }
}

【讨论】:

  • 我已经在我的基类中实现了它......并触发了集合的 Onproperty Changed
  • 是的,但是如果集合本身发生变化(如果添加或删除项目),则只会更新,如果项目的属性发生变化,则不会更新单个项目。
【解决方案2】:

首先,在 wpf 的 ListView 之前,您的记录数实际上什么都不是,因为它使用了 VirtualizingStackPanel。

除了PropertyChange Notification的确切解决方案外,您还应该考虑看看deferred execution的概念。您似乎将所有内容都转换为一个列表,这将导致一次强制枚举结果集。

让我们考虑一下您的代码:

_people= GetAll().ToList();  
//The result of GetAll is enumerated and a solid list is created

List<Person> allPeople = (from person in _people 
                          select new PersonViewModel(person)).ToList(); 
// another list created

AllPeople = new ObservableCollection<PersonViewModel>(allPeople); 
// ObservableCollection created out of list

让我们稍微调整一下:

_people= GetAll(); // The result is just referred by _people

IEnumerable<Person> allPeople = (from person in _people 
                                 select new PersonViewModel(person)); 
// IEnumerable is just provided with a query. No other operation is done

AllPeople = new ObservableCollection<PersonViewModel>(allPeople); 
// The ObservableCollection requests element from allPeople 
// which in turn requests from the query 
// which in turn requests from _people 
// which enumerates the result of GetAll() and yields the result. 

因此您可以避免创建临时列表。

此外,即使 GetAll() 方法不返回 IEnumerable,也可以使其返回。

你可以看看
IEnumerable
IQueryable
yield

【讨论】:

  • 感谢您将列表放入 IEnumerable 集合的建议。我主要关心的是这里 IEnumerable allPeople = (from person in _people select new PersonViewModel(person));因为我有很多方法调用来设置 PersonViewModel 上的属性。每条记录都需要花费大量时间来遍历所有方法。但是现在把它放到 IEnumerable 之后不需要太多时间,但是当调试点转到 AllPeople = new ObservableCollection(allPeople);行加载需要一些明显的时间
  • @user311945:在某一时刻,无论如何都必须创建实体列表,因此需要时间。但它不应该像您指定的那样花费太多时间。对于数千个项目,应该不到一秒。您能否发布 PersonViewModel 构造函数的代码和其他您认为耗时的事情。使用 Stopwatch 类。
猜你喜欢
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2012-09-17
  • 1970-01-01
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多