views:

73

answers:

2

Hi All,

I'm sure there's an "easy" answer to this, but for the moment it escapes me.

In an MVVM application, I have a property that is a ObservableCollection, used for displaying some set of elements on the view.

private readonly ObservableCollection<MyType> mMyCollection = 
    new ObservableCollection<MyType>();
public ObservableCollection<MyType> MyCollection
{
    get { return mMyCollection; }
}

I want to restrict consumers of this collection from simply using the property to add to the collection (i.e. I want to prevent this from the view):

   viewModel.MyCollection.Add(newThing);   // want to prevent this!

Instead, I want to force the use of a method to add items, because there may be another thread using that collection, and I don't want to modify the collection while that thread is processing it.

public void AddToMyCollection(MyType newItem)
{
    // Do some thread/task stuff here
}

Thanks, wTs

+3  A: 

Wrap your collection in a ReadOnlyCollection before giving it to the client, since you still have your non-readonly reference to it you can change it and they'll see the changes but they can't change it. See here for a sample.

ho1
But of course! Thank you!
Wonko the Sane
@ho1 - That would only work if he didn't want people to add anything at all. Instead, he wants people to be able to add items...but only through his custom method.
Justin Niessner
@Justin Niessner: But as long as he keeps a reference to the original collection that should be fine? I haven't actually tried it but this is a quote from the MSDN page: *if changes are made to the underlying collection, the read-only collection reflects those changes*
ho1
@ho1, @Justin Niessner: Yes, wrapping the collection works fine!While Justin's answer would be acceptable, this one works better for me in this simple case. I would implement Justin's if I were to be doing more complex operations on the collection.
Wonko the Sane
@ho1 - Maybe I misunderstand the requirement. It seems like he doesn't want anybody to be able to call Add (at all). Working with the ObservableCollection would never force the use of his custom Add method.
Justin Niessner
+2  A: 

While it would require some work, the only way I can think to accomplish your goal is to create a new class, inherit from ObservableCollection<MyType> and hide the Add() method (via the new keyword).

You could even implement AddToMyCollection(MyType newItem) as:

public new void Add(MyType newItem)
{
    // Do some thread/task stuff here
    // And call base.Add() if you need
}

That way, the usage of your custom method is transparent.

If you didn't want anybody to be able to add items (through Add() or your custom method), you could simply return a ReadOnlyCollection which wouldn't allow anybody to add anything.

Justin Niessner