如何从其他窗体更新XamDataGrid数据源?解决跨窗体更新时的对象引用错误
问题分析与解决方案
首先,咱们先拆解你遇到的两个核心问题:报错原因,以及跨窗体更新XamDataGrid的最佳实践。
为什么会触发那个对象引用错误?
你代码里的问题主要出在两个地方:
- 集合类型不匹配:
List(Of T)本身不支持数据变更通知,而且你用Concat返回的是一个只读的IEnumerable(Of T),XamDataGrid无法正确绑定这种临时枚举集合,容易引发绑定异常。 - Shared成员的访问风险:虽然你定义了
Public Shared List(Of Artikelstammdaten),但直接通过类名MainWindow访问时,如果主窗体实例的生命周期有问题(比如还没初始化就访问),就会触发那个"需要对象引用"的报错。
跨窗体更新XamDataGrid的最佳实践
第一步:替换成可观察集合
把主窗体里的普通List改成ObservableCollection(Of T)——它实现了INotifyCollectionChanged接口,能自动通知XamDataGrid刷新UI,这是WPF/Silverlight控件绑定的标配:
' 在MainWindow中定义共享的可观察集合 Public Shared listArtikelstammdaten As New ObservableCollection(Of Artikelstammdaten)() ' 主窗体加载时绑定数据源 Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded dgArticleMasterData.DataSource = listArtikelstammdaten End Sub
第二步:选择合适的跨窗体通信方式
推荐两种解耦且可靠的方式:
方式一:传递主窗体实例(简单直接)
打开子窗体时,把当前主窗体的实例传进去,避免直接通过类名访问Shared成员:
' 在MainWindow中打开子窗体的代码 Dim childForm As New YourChildForm(Me) ' 子窗体需要有接收MainWindow实例的构造函数 childForm.Show()
子窗体的代码修改:
Private _mainWindow As MainWindow ' 子窗体构造函数,接收主窗体实例 Public Sub New(mainWindow As MainWindow) InitializeComponent() _mainWindow = mainWindow End Sub Private Sub Add_Click(sender As Object, e As RoutedEventArgs) ' 获取要追加的新数据 Dim newData = CType(Import.ComparedAccessData, IEnumerable(Of Artikelstammdaten)) ' 直接往可观察集合里加元素,自动触发UI更新 For Each item In newData _mainWindow.listArtikelstammdaten.Add(item) Next Me.Close() End Sub
方式二:使用事件通知(更解耦,适合复杂场景)
如果不想让子窗体直接依赖主窗体,可以用事件机制传递数据:
' 子窗体中定义事件,用于传递要追加的数据 Public Event DataReadyToAdd(ByVal newData As IEnumerable(Of Artikelstammdaten)) Private Sub Add_Click(sender As Object, e As RoutedEventArgs) Dim newData = CType(Import.ComparedAccessData, IEnumerable(Of Artikelstammdaten)) ' 触发事件,把数据传递给主窗体 RaiseEvent DataReadyToAdd(newData) Me.Close() End Sub
主窗体订阅事件并处理:
' 在MainWindow中打开子窗体时订阅事件 Dim childForm As New YourChildForm() AddHandler childForm.DataReadyToAdd, AddressOf OnChildFormDataReady childForm.Show() ' 处理事件的方法 Private Sub OnChildFormDataReady(newData As IEnumerable(Of Artikelstammdaten)) For Each item In newData listArtikelstammdaten.Add(item) Next End Sub
总结
你原来的代码之所以报错,本质是用了不支持绑定的集合类型,加上跨窗体访问方式不够严谨。换成ObservableCollection后,不需要重新赋值DataSource,直接添加元素就能自动刷新UI;再通过实例传递或事件通知的方式跨窗体通信,既能解决报错,又能让代码更健壮。
内容的提问来源于stack exchange,提问作者user17151986
相关产品推荐
相关产品推荐

