C# 通过ListCollectionView的ObservableCollection显示不正确的项目列表
C#:C# 通过ListCollectionView的ObservableCollection显示不正确的项目列表,c#,wpf,data-binding,observablecollection,listcollectionview,C#,Wpf,Data Binding,Observablecollection,Listcollectionview,C#: 公共部分类主窗口:窗口 { 私有只读ViewModel虚拟机; 公共主窗口() { 初始化组件(); vm=新的ViewModel(); DataContext=vm; } 私有无效按钮\u单击(对象发送者,路由目标e) { vm.Models.RemoveAt(0); } } 公共类视图模型 { 公共可观测集合模型{get;set;} 公共ListCollectionView视图{get;set;} 公共视图模型() { 模型=新的ObservableCollection() { 新模
公共部分类主窗口:窗口
{
私有只读ViewModel虚拟机;
公共主窗口()
{
初始化组件();
vm=新的ViewModel();
DataContext=vm;
}
私有无效按钮\u单击(对象发送者,路由目标e)
{
vm.Models.RemoveAt(0);
}
}
公共类视图模型
{
公共可观测集合模型{get;set;}
公共ListCollectionView视图{get;set;}
公共视图模型()
{
模型=新的ObservableCollection()
{
新模型(){Name=“Gordon Freeman”},
新模型(){Name=“Isaac Kleiner”},
新模型(){Name=“Eli Vance”},
新模型(){Name=“Alyx Vance”},
};
Models.CollectionChanged+=(s,e)=>View.Refresh();
视图=新ListCollectionView(模型);
}
}
公共类模型
{
公共字符串名称{get;set;}
公共重写字符串ToString()
{
返回名称;
}
}
XAML:
点击
ObservaleCollection包含4个元素,ListBox按预期显示所有4个元素。单击按钮时,将删除ObservableCollection的第一个元素。然而,列表框现在只显示第二个和第三个。看起来第1个和第4个已被删除
如果行Models.CollectionChanged+=(s,e)=>View.Refresh()代码>在<代码>视图=新建ListCollectionView(模型)之后移动代码>(或完全注释掉)事情按预期进行
为什么?
另外,这是一个更大的谜题中的一个简单部分。在这个小示例中,我意识到我不需要调用View.Refresh()集合上的代码>已更改,列表框将自动更新。我猜想刷新会干扰视图的自动更新。可能视图在构造函数中也订阅了CollectionChanged
,因此如果在视图执行并调用refresh之前订阅了事件,则在集合更改和视图自己的更新之间会得到不需要的更新
e、 g
项目0已删除->通知事件侦听器
=>处理程序:刷新()->重建视图=>项被删除。
=>查看处理程序:事件参数显示:项目X已删除->删除项目X
这仍然不能解释为什么第一个和最后一个项目被删除,但对我来说似乎是合理的
如果订阅在视图实例化之后:
项目0已删除->通知事件侦听器
=>查看处理程序:事件参数显示:项目X已删除->删除项目X
=>处理程序:Refresh()->Rebuild view=>没有任何更改。ListView刷新似乎有问题。如果将labe/TextBlock绑定到ListView.Items.Count,您将看到列表中仍有3个项目(第一次删除后)。请尝试不要使用new关键字定义您的新实例listCollectionView
。改用以下方法
public partial class MainWindow : Window
{
private readonly ViewModel vm;
public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
DataContext = vm;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.Models.RemoveAt(0);
}
}
public class ViewModel
{
public ObservableCollection<Model> Models { get; set; }
public ListCollectionView View { get; set; }
public ViewModel()
{
Models = new ObservableCollection<Model>()
{
new Model() { Name = "Gordon Freeman" },
new Model() { Name = "Isaac Kleiner" },
new Model() { Name = "Eli Vance" },
new Model() { Name = "Alyx Vance" },
};
Models.CollectionChanged += (s, e) => View.Refresh();
View = new ListCollectionView(Models);
}
}
public class Model
{
public string Name { get; set; }
public override string ToString()
{
return Name;
}
}
即使您正在将模型
类包装在可观察集合
中,您仍然需要为其实现INotifyPropertyChanged
。我已经多次碰到这个问题,现在我记得从最低的构建块,即Model
开始进行故障排除
var sortedCities = CollectionViewSource.GetDefaultView(Models);
另外,在您的视图模型中
,当INotifyPropertyChanged
正确实现时,您不需要下面的行<代码>INotifyPropertyChanged
将为您更新UI
public class Model : INotifyPropertyChanged
{
#region INotify Implementation
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
#endregion
public string _Name;
public string Name {
get { return _Name; }
set { _Name = value; NotifyPropertyChanged("Name"); }
}
public override string ToString()
{
return Name;
}
}
这听起来不错,但我想我们还不能确定…为什么最后一项会被删除?您能解释一下原因吗?CollectionViewSource跟踪Ilist集合的所有视图。使用new将创建集合视图的新实例,并将其添加到CollectionViewSource。使用GetDefaultView将为您提供集合的默认视图,并保护您的代码不具有多个视图。因此,您可以在单个视图上添加排序和筛选。
Models.CollectionChanged += (s, e) => View.Refresh();
View = new ListCollectionView(Models);