ItemsSource变更时ListBox未更新,DEL按钮失效问题排查
你遇到的问题核心原因很明确:DEL按钮自己创建了一个新的ViewModel实例,导致删除操作没有作用在页面绑定的那个ObservableCollection<User>上。
为什么会这样?
看你XAML里DEL按钮的代码:
<Button Content="DEL" Command="{Binding DelUsers_OASUCommand}" ...> <Button.DataContext> <local:ViewModel /> </Button.DataContext> </Button>
这里你给每个DEL按钮都单独设置了一个新的ViewModel作为DataContext。当你点击DEL按钮时,执行的是这个新ViewModel里的DelUsers_OASUMethod——这个新ViewModel的Users_OASU是全新的集合,删除操作只会修改它,而页面ListBox绑定的是MainView构造函数里设置的那个ViewModel的集合,两者完全无关,所以ListBox自然不会更新。
修复步骤
1. 移除DEL按钮的DataContext设置
删掉<Button.DataContext>这一段,让按钮继承父级的DataContext链,这样我们才能绑定到页面的ViewModel命令。
2. 正确绑定DEL按钮的Command和CommandParameter
因为ListBox的DataContext是你的ViewModel,而ListBoxItem的DataContext是单个User对象,所以:
- Command需要绑定到ListBox的DataContext(也就是ViewModel)里的
DelUsers_OASUCommand - CommandParameter直接绑定当前的
User对象即可,不用复杂的RelativeSource路径
修改后的DEL按钮代码:
<Button Content="DEL" Command="{Binding DataContext.DelUsers_OASUCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" CommandParameter="{Binding}" />
3. 简化ViewModel里的删除方法
现在CommandParameter直接传入的是要删除的User对象,所以可以简化DelUsers_OASUMethod,不用再查询:
private void DelUsers_OASUMethod(object arg) { if (arg is User userToDelete) { Users_OASU.Remove(userToDelete); } }
验证修复效果
这样修改后,点击DEL按钮时,命令会正确调用页面ViewModel的删除方法,直接从绑定的ObservableCollection<User>中移除对应的User,而ObservableCollection本身会自动通知UI更新,ListBox就会同步显示变化了。
内容的提问来源于stack exchange,提问作者Dmitri Veselov

