WinUI 3 ListView:如何在MVVM模式下以编程方式选中项?
实现ListView选中项的持久化与恢复
一、保存选中项到数据库
直接序列化ObservableCollection<Party>易引发序列化问题,更稳妥的方式是保存每个选中Party的唯一标识(比如Id字段):
- 提取选中项的主键集合
// 假设Party类以Id作为唯一标识 var selectedIds = ViewModel.SelectedPartys.Select(p => p.Id).ToList();
- 将主键集合存入数据库
根据你使用的数据库框架(如EF Core、SQLite)执行插入/更新操作,示例(EF Core):
using(var db = new YourDbContext()) { // 单用户场景下先清空旧记录 db.SelectedPartyRecords.RemoveRange(db.SelectedPartyRecords); // 批量添加新记录 foreach(var id in selectedIds) { db.SelectedPartyRecords.Add(new SelectedPartyRecord { PartyId = id }); } await db.SaveChangesAsync(); }
二、从数据库恢复预选中项
需在ListView数据源(PartysOC)加载完成后执行恢复操作:
- 从数据库加载保存的主键集合
List<int> savedSelectedIds; using(var db = new YourDbContext()) { savedSelectedIds = db.SelectedPartyRecords.Select(r => r.PartyId).ToList(); }
- 匹配数据源并设置选中状态
为避免SelectionChanged事件重复触发导致SelectedPartys重复添加,先临时取消事件订阅,完成后再重新订阅:
// 临时移除事件处理 LV_Partys.SelectionChanged -= LV_Partys_SelectionChanged; // 遍历保存的Id,找到对应项并设置选中 foreach(var id in savedSelectedIds) { var targetParty = ViewModel.PartysOC.FirstOrDefault(p => p.Id == id); if(targetParty != null) { LV_Partys.SelectedItems.Add(targetParty); // 同步更新ViewModel的SelectedPartys,避免后续事件重复操作 if(!ViewModel.SelectedPartys.Contains(targetParty)) { ViewModel.SelectedPartys.Add(targetParty); } } } // 重新订阅事件 LV_Partys.SelectionChanged += LV_Partys_SelectionChanged;
关键注意事项
- 必须确保
PartysOC数据完全加载后再执行恢复,可放在页面Loaded事件或PartysOC的CollectionChanged事件(确认数据加载完成后)中执行。 - 若
Party类未重写Equals和GetHashCode,Contains方法可能无法正确判断对象是否存在,建议重写:
public class Party { public int Id { get; set; } public string Name { get; set; } public override bool Equals(object obj) { return obj is Party party && Id == party.Id; } public override int GetHashCode() { return HashCode.Combine(Id); } }
内容的提问来源于stack exchange,提问作者tinmac
相关产品推荐
相关产品推荐

