views:

36

answers:

1

I want to make a deep copy of an ObservableCollection in Silverlight 4 in order to detect changes in the items in the list. Since ICloneable isn't available in SL how can I do this?

OR - is there a better way to check for changes in the items in the collection?

A: 

Sure. If your individual implement INotifyPropertyChanged, then you can register and listen for that.

Basically, your individual items should implement the property changed. Here is a Widget that does this:

public class Widget : INotifyPropertyChanged
{
    private int _id;

    public int Id
    {
        get { return _id; }
        set
        {
            _id = value;
            RaisePropertyChanged("Id");
        }
    }

    private string _name;

    public string Name
    {
        get { return _name; }
        set
        {
            _name = value;
            RaisePropertyChanged("Name");
        }
    }



    private void RaisePropertyChanged(string propertyName)
    {
        var handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Next, you need to manage the observable collection and register to collection change events. When widgets are added, you hook into the property change. When they are removed, you unhook:

public class WidgetViewModel
{
    public WidgetViewModel()
    {
        Widgets = new ObservableCollection<Widget>();
        Widgets.CollectionChanged += Widgets_CollectionChanged;
    }

    void Widgets_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        if (e != null && e.NewItems != null)
        {
            foreach (var widget in e.NewItems.OfType<Widget>())
            {
                widget.PropertyChanged += WidgetViewModel_PropertyChanged;
            }
        }

        if (e != null && e.OldItems != null)
        {
            foreach(var widget in e.OldItems.OfType<Widget>())
            {
                widget.PropertyChanged -= WidgetViewModel_PropertyChanged;
            }
        }
    }

    void WidgetViewModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        switch(e.PropertyName)
        {
            case "Id":
                break;
            case "Name":
                break;
            default:
                break;
        }
    }
    public ObservableCollection<Widget> Widgets { get; private set; }
}

In the property change, you can deal with whatever is going on.

Jeremy Likness