我正在使用ListView控件来显示一些数据行.有一个后台任务接收列表内容的外部更新.新接收的数据可能包含更少,更多或相同数量的项目,并且项目本身也可能已更改.
在ListView.ItemsSource绑定到OberservableCollection(_itemList),以便更改_itemList应在也可以看到ListView.
_itemList = new ObservableCollection<PmemCombItem>();
_itemList.CollectionChanged += new NotifyCollectionChangedEventHandler(OnCollectionChanged);
L_PmemCombList.ItemsSource = _itemList;
Run Code Online (Sandbox Code Playgroud)
为了避免刷新完整的ListView,我将新检索的列表与当前_itemList进行简单比较,更改不相同的项目,并在必要时添加/删除项目.集合"newList"包含新创建的对象,因此替换_itemList中的项目正确地发送"刷新"通知(我可以使用OnCollectionChangedObservableCollection 的事件处理程序进行记录)
Action action = () =>
{
for (int i = 0; i < newList.Count; i++)
{
// item exists in old list -> replace if changed
if (i < _itemList.Count)
{
if (!_itemList[i].SameDataAs(newList[i]))
_itemList[i] = newList[i];
}
// new list contains more items -> add items
else
_itemList.Add(newList[i]);
}
// new list contains less items -> remove items
for (int i = _itemList.Count - 1; i >= newList.Count; i--)
_itemList.RemoveAt(i);
};
Dispatcher.BeginInvoke(DispatcherPriority.Background, action);
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果在这个循环中更改了很多项目,那么ListView就不会刷新,屏幕上的数据会保持原样...而这我不明白.
甚至更简单的版本(交换所有元素)
List<PmemCombItem> newList = new List<PmemCombItem>();
foreach (PmemViewItem comb in combList)
newList.Add(new PmemCombItem(comb));
if (_itemList.Count == newList.Count)
for (int i = 0; i < newList.Count; i++)
_itemList[i] = newList[i];
else
{
_itemList.Clear();
foreach (PmemCombItem item in newList)
_itemList.Add(item);
}
Run Code Online (Sandbox Code Playgroud)
工作不正常
这有什么线索吗?
UPDATE
如果我在更新所有元素后手动调用以下代码,一切正常
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
Run Code Online (Sandbox Code Playgroud)
但当然这会导致UI更新我仍想避免的所有内容.
小智 31
这是我必须要做的才能让它发挥作用.
MyListView.ItemsSource = null;
MyListView.ItemsSource = MyDataSource;
Run Code Online (Sandbox Code Playgroud)
小智 25
更改后,您可以使用以下内容刷新Listview,这样更容易
listView.Items.Refresh();
Run Code Online (Sandbox Code Playgroud)
我知道这是一个老问题,但我只是偶然发现了这个问题。我真的不想对已更新的字段使用空分配技巧或刷新。
所以,在查看 MSDN 之后,我发现了这篇文章:https : //docs.microsoft.com/en-us/dotnet/api/system.componentmodel.inotifypropertychanged?redirectedfrom= MSDN &view=netframework-4.7.2
总结一下,你只需要实现这个接口的item,它就会自动检测到这个对象可以被观察到。
public class MyItem : INotifyPropertyChanged
{
private string status;
public string Status
{
get => status;
set
{
OnPropertyChanged(nameof(Status));
status = value;
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Run Code Online (Sandbox Code Playgroud)
因此,每次有人更改Status. 而且,在您的情况下,列表视图将在PropertyChanged事件上自动添加一个处理程序。
这并不能真正处理您的情况(添加/删除)。但为此,我建议您查看BindingList<T>
https://docs.microsoft.com/en-us/dotnet/api/system.componentmodel.bindinglist-1?view=netframework-4.7.2
使用相同的模式,您的列表视图将在不使用任何技巧的情况下正确更新。
您不应ItemsSource在ListView每次可观察集合更改时重置。只需设置适当的绑定即可。在xaml:
<ListView ItemsSource='{Binding ItemsCollection}'
...
</ListView>
Run Code Online (Sandbox Code Playgroud)
在代码隐藏(建议使用MVVM)属性中,将负责持有_itemList:
public ObservableCollection<PmemCombItem> ItemsCollection
{
get
{
if (_itemList == null)
{
_itemList = new ObservableCollection<PmemCombItem>();
}
return _itemList;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
37569 次 |
| 最近记录: |