Nostromo
Nostromo

Reputation: 1276

Working with ObservableCollections in WPF and MVVM

I'm fairly new to WPF and still try to get the feeling on how to do something with built-in functions rather than inventing the wheel on my own again.

Today I stumbled upon a problem, that I couldn't solve with built-in functions and the possible ways I could think of I didn't like very much. So hopefully you can point me in the right direction or even can name a clever way with built-in functions.

So, for the sake of simplicity let's say I'd like to write a ViewModel for the MailMessage class that can be found in the System.Net.Mail namespace.

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

Public Class MailMessageViewModel
    Private _message As MailMessage

    ...

End Class

A MailMessage object has (among others) a property To of type MailAddressCollection containing all the recipients for my e-mail as MailAddress objects.

In my ViewModel I wrap this collection of MailAddress objects into an ObservableCollection.

And here's my first question, how do I do that. Do I use:

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

or do I use:

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

My view model now has a bindable property Recipients.

Now I'd like to be able to delete an e-mail address from the To collection of my MailMessage. But when I delete an address from the ObservableCollection, my UI gets updated properly, but the To collection stays untouched. If I delete directly from the To collection of my MailMessage, the ObservableCollection and therefore my UI don't reflect the changes.

Do I really have to wire the ObservableCollection and the corresponding source collection manually by using the CollectionChanged event or by doing all changes twice (in the ObservableCollection and in the real collection)? Or is there any clever WPF way I don't know of?

Upvotes: 0

Views: 147

Answers (2)

Babbillumpa
Babbillumpa

Reputation: 1864

If the changes always go from the ObservableCollection to the original List, i think that you could add a handler to 'CollectionChanged' event of the ObservableCollection. I think that doing it this way won't be so onerous.

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

Obviously, if you want, you can also handle the modify and the adding of elements into the ObservableCollection using the informations into the NotifyCollectionChangedEventArgs parameter.

Upvotes: 1

user1228
user1228

Reputation:

Don't "wrap" anything.

Simply create a View Model containing properties needed to send your mail message.

At some point in future, you'll actually be sending the message. For example, the user clicks a Send button that fires an ICommand somewhere. At this time, convert your ViewModel into a MailMessage.

You cannot "wrap" one collection within another without lots of code. It only takes a few minutes to copy property values from an instance of one type to an instance of another type.

Upvotes: 2

Related Questions