在 WPF 和 MVVM 中使用 ObservableCollections

Working with ObservableCollections in WPF and MVVM

我是 WPF 的新手,我仍然试图了解如何使用 built-in 函数做某事,而不是自己重新发明轮子。

今天我偶然发现了一个问题,我无法用 built-in 函数解决这个问题,而且我不太喜欢我能想到的可能方法。所以希望你能给我指出正确的方向,甚至可以用 built-in 函数命名一个聪明的方法。

因此,为了简单起见,假设我想为可以在 System.Net.Mail 命名空间中找到的 MailMessage class 编写一个 ViewModel。

Imports System.Collections.ObjectModel
Imports System.Net.Mail

Public Class MailMessageViewModel
    Private _message As MailMessage

    ...

End Class

A MailMessage object 有一个 属性 To 类型 MailAddressCollection 包含我的 e-mail 的所有收件人作为 MailAddress objects.

在我的 ViewModel 中,我将 MailAddress object 中的 collection 包装到一个 ObservableCollection 中。

这是我的第一个问题,我该怎么做。我是否使用:

    Public ReadOnly Property Recipients As ObservableCollection(Of MailAddress)
        Get
            Return New ObservableCollection(Of MailAddress)(_message.To)
        End Get
    End Property

或者我使用:

Private _recipients As ObservableCollection(Of MailAddress)
Public ReadOnly Property Recipients As ObservableCollection(Of MailAddress)
    Get
        If _recipients Is Nothing Then
            _recipients = New ObservableCollection(Of MailAddress)(_message.To)
        End If

        Return _recipients
    End Get
End Property

我的视图模型现在有一个可绑定的 属性 Recipients.

现在我希望能够从我的 MailMessageTo collection 中删除一个 e-mail 地址。 但是当我从 ObservableCollection 中删除一个地址时,我的 UI 得到正确更新,但 To collection 保持不变。如果我直接从 MailMessageTo collection 中删除,ObservableCollection 和 UI 不会反映更改。

我真的必须通过使用 CollectionChanged 事件或对所有更改进行两次(在 ObservableCollection 中)手动连接 ObservableCollection 和相应的源 collection而在真实的 collection) 中?或者有什么我不知道的聪明的 WPF 方式吗?

不要"wrap"任何东西。

只需创建一个视图模型,其中包含发送邮件消息所需的属性。

在将来的某个时刻,您将真正发送消息。例如,用户单击发送按钮,在某处触发 ICommand。 此时,将你的ViewModel转换成一个MailMessage.

如果没有 lots 代码,您不能 "wrap" 一个集合包含另一个集合。只需几分钟即可将 属性 值从一种类型的实例复制到另一种类型的实例。

如果更改总是从 ObservableCollection 到原始列表,我认为您可以向 ObservableCollection 的 'CollectionChanged' 事件添加一个处理程序。我觉得这样做不会那么麻烦。

AddHandler Recipients.CollectionChanged, AddressOf RecipientsCollChanged

.....

Private Sub RecipientsCollChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
    If e.OldItems IsNot Nothing Then
        For Each elem In e.OldItems
            _message.To.Remove(elem)
        Next
    End If
End Sub

显然,如果需要,您还可以使用 NotifyCollectionChangedEventArgs 参数中的信息处理修改和向 ObservableCollection 添加元素。