1
votes

I have a recursive viewmodel that uses for a treeview. The problem is everytime I delete a Group Item or Entry Item. The treeview cannot reflect the change immediately until I force it by treeview.Items.Refresh(). My guess is the ObservableCollection Items did get notified. Could you one please point me out. Thanks.

ViewModel

public class Group:ViewModelBase
{
    private int _key;

    public int Key
    {
        get { return _key; }
        set { _key = value; OnPropertyChanged("Key"); }
    }
    private string _name;

    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged("Name"); }
    }
    private bool _isexpanded;

    public bool IsExpanded
    {
        get { return _isexpanded; }
        set { _isexpanded = value; OnPropertyChanged("IsExpanded"); }
    }
    private int _order;

    public int Order
    {
        get { return _order; }
        set { _order = value; OnPropertyChanged("Order"); }
    }
    private int _grouporder;

    public int GroupOrder
    {
        get { return _grouporder; }
        set { _grouporder = value; OnPropertyChanged("GroupOrder"); }
    }
    private string _error;

    public string Error
    {
        get { return _error; }
        set { _error = value; OnPropertyChanged("Error"); }
    }
    private ObservableCollection<Group> _subgroups;

    public ObservableCollection<Group> SubGroups
    {
        get { return _subgroups; }
        set { _subgroups = value; 
            OnPropertyChanged("SubGroups");
            OnPropertyChanged("Entries");
        }
    }
    private ObservableCollection<Entry> _entries;

    public ObservableCollection<Entry> Entries
    {
        get { return _entries; }
        set { _entries = value;
            OnPropertyChanged("SubGroups");
            OnPropertyChanged("Entries"); }
    }


    public ObservableCollection<object> Items
    {
        get
        {
            ObservableCollection<object> childNodes = new ObservableCollection<object>();
            foreach (var entry in this.Entries)
                childNodes.Add(entry);
            foreach (var group in this.SubGroups)
                childNodes.Add(group);
            return childNodes;
        }

    }
}

Binding:

 public MainWindow()
    {
        InitializeComponent();
        treeview.ItemsSource = Groups;
        this.DataContext = this;


    }
1

1 Answers

1
votes

The issue is that you break the link with the original collections.

So I can imagine two solutions:

1) Register for changes on Entries and SubGroups and apply them back to Items:

private ObservableCollection<object> items;
public ObservableCollection<object> Items
{
    get
    {
        if (items == null)
        {
            items = new ObservableCollection<object>();
            foreach (var entry in this.Entries)
                items.Add(entry);
            foreach (var group in this.SubGroups)
                items.Add(group);


            this.Entries.CollectionChanged += (s, a) =>
            {
                if (/*add some stuff*/)
                {
                    items.Add(/*some stuff*/)
                }
                else if (/*remove some stuff*/)
                {
                    items.Remove(...)
                }
            };

            this.SubGroups.CollectionChanged += ...

            return items;
        }
    }
}

And you would reset items by setting it to null each time you set Entries or SubGroups so that it is regenerated next time, taking into account new Entries and SubGroups.

2) Try with a CompositeCollection:

new CompositeCollection
{
    new CollectionContainer { Collection = this.Entries },
    new CollectionContainer { Collection = this.SubGroups }
};

Not sure for this second solution but it would be quite elegant, worth a try...