WPF嵌套ListView数据绑定报ItemsSource操作无效错误
问题原因
触发operation-is-not-valid-while-itemssource-is-in-use-access错误的核心逻辑是:当列表控件的ItemsSource已经绑定数据源时,直接向控件的Items集合写入内容,会和绑定的数据源产生冲突。
结合你的场景,添加内层ListView的DataTemplate就报错、移除就恢复正常,问题100%出在XAML书写结构上:你把内层list2的项模板DataTemplate直接写在了ListView的开闭合标签内部,没有显式声明属于ItemTemplate属性。WPF会默认把ListView标签中间的直接子元素当成要手动添加到Items集合的项,这时候和已经绑定的marks数据源冲突,直接抛出异常。
错误写法示例:
<!-- 错误写法,会直接触发该异常 --> <ListView x:Name="list2" ItemsSource="{Binding marks}"> <DataTemplate> <TextBlock Text="{Binding}" MouseLeftButtonDown="MarkItem_Click"/> </DataTemplate> </ListView>
修复方法
把内层ListView的DataTemplate显式包裹在<ListView.ItemTemplate>标签内,明确告诉WPF这是项模板,不是要手动添加的列表项即可,参考正确写法:
<GridViewColumn Header="Marks"> <GridViewColumn.CellTemplate> <DataTemplate> <ListView x:Name="list2" ItemsSource="{Binding marks}"> <!-- 显式声明ItemTemplate属性,不要直接把DataTemplate放在ListView标签下 --> <ListView.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding}" MouseLeftButtonDown="MarkItem_Click"/> </DataTemplate> </ListView.ItemTemplate> </ListView> </DataTemplate> </GridViewColumn.CellTemplate> </GridViewColumn>
其他需要调整的细节
- 你定义的
Test类中name和marks属性都是默认私有访问级别,WPF绑定要求属性必须是public才能正常访问,记得修改访问修饰符,否则后续会出现绑定拿不到值的问题:public class Test { public string name {get;set;} public List<string> marks {get; set;} } - 如果后续需要对marks集合做增删操作后自动同步UI,把
List<string>替换为ObservableCollection<string>即可。 - 所有已经通过ItemsSource绑定的列表控件,不要在后台直接调用
Items.Add()、Items.Remove()、Items.Clear()这类方法,要修改数据直接操作绑定的源集合就行,不然也会触发同样的异常。
内容的提问来源于stack exchange,提问作者murmansk
相关产品推荐
相关产品推荐

