WPF页面切换按钮触发InvalidOperationException错误求助
先直接点出你遇到的错误核心:
System.InvalidOperationException : 'A TwoWay or OneWayToSource binding cannot work on the read-only property 'Boozes' of type 'DatabaseBoozeWpf.ViewModels.MainWindowVM'.'
这个报错的原因其实很直白:你把搜索框的Text属性绑定到了只读的集合属性Boozes上,而WPF里TextBox的默认绑定模式是TwoWay。当你在SearchBox里输入内容时,WPF会自动尝试把输入的文本赋值给Boozes,但Boozes的setter是private的,而且它本身是List<Booze>类型,和TextBox的string类型完全不匹配,这就直接触发了这个异常。
你看MainWindow.xaml里这段明显有问题的绑定代码:
<TextBox Height="27" HorizontalAlignment="Left" Margin="10,92,0,0" Name="SearchBox" VerticalAlignment="Top" Width="130" Background="#FF51C1FA" Text="{Binding Boozes, UpdateSourceTrigger=PropertyChanged}" >
搜索框的文本怎么能绑定到酒水集合呢?这完全是绑定对象搞错了。
具体解决步骤
1. 给ViewModel加个搜索专用属性
先在你的MainWindowVM里添加一个专门用来接收搜索输入的字符串属性,比如叫SearchText,你的BaseVM已经实现了INotifyPropertyChanged,直接用就行:
private string _searchText; public string SearchText { get => _searchText; set { _searchText = value; NotifyPropertyChanged(nameof(SearchText)); // 这里还可以加搜索过滤逻辑,比如根据输入过滤Boozes集合 // FilterBoozesBySearchText(); } }
2. 修改TextBox的绑定
把MainWindow.xaml里SearchBox的绑定改成刚才加的SearchText,现在属性是可写的,默认的TwoWay模式也能正常工作了:
<TextBox Height="27" HorizontalAlignment="Left" Margin="10,92,0,0" Name="SearchBox" VerticalAlignment="Top" Width="130" Background="#FF51C1FA" Text="{Binding SearchText, UpdateSourceTrigger=PropertyChanged}" >
3. 额外说下页面切换的小问题
看你切换页面的代码:
private void exitAddItemWindow(object sender, RoutedEventArgs e) { MainWindow sK = new MainWindow(); sK.Show(); this.Close(); }
这种每次新建MainWindow实例的方式,会导致ViewModel重新初始化,如果项目在其他电脑正常运行,大概率是那些电脑上没人操作过搜索框——只要不输入内容,WPF就不会触发绑定源的更新,自然不会报错。要是想优化页面切换,建议用MVVM的导航机制,或者复用已有的窗口实例,但当前核心问题还是绑定错误。
4. 确认集合绑定的正确性
另外你在ListBox里用CollectionViewSource绑定Boozes是没问题的,因为那是单向绑定(从ViewModel到View),不会尝试修改Boozes,所以只有TextBox的绑定才会触发错误。
为啥其他电脑能正常跑?
很简单——那些电脑上没人在搜索框里输入过内容。只有当你在SearchBox输入文字时,UpdateSourceTrigger=PropertyChanged会立刻触发WPF更新绑定源,也就是尝试给Boozes赋值,这时候才会暴露出只读属性的问题。
内容的提问来源于stack exchange,提问作者Rkurel

