ByRef传递ObservableCollection后在事件中变为空的问题求助
问题分析与解决方案
首先,咱们得搞清楚为什么会出现这个矛盾:在LoadAnnos方法里明明看到集合有值,但事件触发后ViewModel里的AnnotationList却为空。核心问题出在ByRef传递引用类型时的赋值逻辑上——这个误区很容易踩中。
你在LoadAnnos里直接给annotationList赋值了一个新的ObservableCollection对象:
annotationList = XMLSerialization.Deserialize()
虽然用了ByRef,但这里的操作是把参数指向了一个全新的对象实例。ViewModel里的AnnotationList变量还是持有原来的空集合引用,两者现在指向的是完全不同的对象——这就是为什么事件里访问AnnotationList时它还是空的。
修复方案一:复用原集合实例(推荐)
不要重新创建集合实例,而是复用原集合的引用,清空后再添加反序列化出来的元素。修改LoadAnnos方法如下:
Public Sub LoadAnnos(ByRef annotationList As ObservableCollection(Of PdfMarkupAnnotationDataWrapper), pdfViewer As PdfViewerControl) ' 先清空原集合的内容 annotationList.Clear() ' 反序列化得到新的集合数据 Dim deserializedList = XMLSerialization.Deserialize() ' 将反序列化的元素逐个添加到原集合中 For Each anno In deserializedList annotationList.Add(anno) AddAnnotationsToPdf(pdfViewer, anno) Next End Sub
这样做的好处:
- ViewModel里的
AnnotationList引用始终没变,所有操作都是在同一个集合实例上进行 - 集合的
CollectionChanged事件会正常触发(如果有UI绑定需求,也能同步更新) - 事件处理方法里访问
AnnotationList时,就能看到最新的元素了
修复方案二:让方法返回新集合
如果你不需要保留原集合的任何绑定或事件订阅,也可以选择让LoadAnnos直接返回反序列化后的集合,然后在ViewModel里直接赋值:
' 修改LoadAnnos为返回集合的函数 Public Function LoadAnnos(pdfViewer As PdfViewerControl) As ObservableCollection(Of PdfMarkupAnnotationDataWrapper) Dim annotationList = XMLSerialization.Deserialize() For Each anno In annotationList AddAnnotationsToPdf(pdfViewer, anno) Next Return annotationList End Function ' 在ViewModel里调用 AnnotationList = _pdfModel.LoadAnnos(pdfViewer)
这种方式更直观,也避免了ByRef传递带来的混淆,适合不需要复用原集合的场景。
内容的提问来源于stack exchange,提问作者Detlef D Soost
相关产品推荐
相关产品推荐

