如何刷新排序后的ObservableCollection绑定视图?按钮重排触发时机问题
问题解决方案
一、修复排序后CollectionView不刷新的问题
你的ViewModel中SortPlayers方法的问题在于,OrderByDescending仅返回排序后的新序列,不会修改原集合UserItems,因此UI无法感知到顺序变化。以下是两种符合你“不想重建集合”需求的修复方式:
方式1:调整ObservableCollection内部顺序(保留原集合实例)
如果UserItems是ObservableCollection<UserItem>,可通过清空后重新添加排序项来更新顺序(ObservableCollection的增删操作会自动触发UI更新):
public void SortPlayers() { var sortedItems = UserItems.OrderByDescending(x => x.CurrentTimeOn).ToList(); UserItems.Clear(); foreach (var item in sortedItems) { UserItems.Add(item); } }
此时视图层的OnPropertyChanged(nameof(VM.UserItems))可省略,因为ObservableCollection的变更会自动通知UI。
方式2:使用ICollectionView(不修改原集合,仅更新视图)
在ViewModel中维护集合视图,直接对视图排序,原集合的实例和元素顺序均保持不变:
- 定义ICollectionView属性:
public ICollectionView UserItemsView { get; private set; }
- 初始化时绑定原集合并设置排序规则:
UserItemsView = CollectionViewSource.GetDefaultView(UserItems); UserItemsView.SortDescriptions.Add(new SortDescription(nameof(UserItem.CurrentTimeOn), ListSortDirection.Descending));
- 修改SortPlayers方法,只需刷新视图:
public void SortPlayers() { UserItemsView.Refresh(); }
- 视图层CollectionView的绑定改为:
<CollectionView ... ItemsSource="{Binding UserItemsView}" ...>
二、解决TapGesture执行后触发排序的问题
ParentChanged事件触发时机早于TapGesture命令,因此无法满足需求。最优方案是在命令执行完成后直接调用排序逻辑,符合MVVM规范:
- 修正ViewModel中的命令执行逻辑(注意你代码中命令名多写了一个Command,应为
StartStopCommand):
private void ExecuteStartStopCommand() { // 执行原按钮业务逻辑,比如更新CurrentTimeOn等操作 // ... // 业务逻辑完成后,立即触发排序 SortPlayers(); }
这样命令执行完毕后自动触发排序,无需在视图层额外处理事件。
另外,你按钮代码中的ParentChanged="ButtonClickedCommand"是错误写法(事件应绑定处理方法而非命令名),建议直接移除该行。
内容的提问来源于stack exchange,提问作者Aeneas
相关产品推荐
相关产品推荐

