views:

38

answers:

3

I am using WPF and C# I have a button that opens a window, which also includes a button that adds an User object item to a listbox and I want the listbox index to be updated after insertion. I understood that the solution is about using observable class of INotifyCollectionChanged but actually I dont know how and where to use them. Can you help me on determining what and where to implement, register, fire etc.


Edit: I succeeded this by Quartermeister's help where my User object is collected in a list, but now I want to do the same thing where my object is collected in a dictionary

+3  A: 

The easiest way is to use System.Collections.ObjectModel.ObservableCollection<T> as your list. This implements INotifyCollectionChanged and INotifyPropertyChanged for you.

You would have a property on your DataContext object of this type, and use data binding on ListBox.ItemsSource to bind it to that property. The ListBox will automatically update its list of elements when the collection changes.

In the class that is your DataContext:

public class MyClass
{
    public ObservableCollection<string> Items { get; set; }
}

In Xaml:

<ListBox ItemsSource="{Binding Items}">
</ListBox>

It sounds like you also want an observable dictionary, but unfortunately there is not one built into the framework. You could try using Dr. Wpf's implementation of ObservableDictionary from his post "Can I bind my ItemsControl to a dictionary?".

Quartermeister
That was a quite easy and helpful solution. Thanks a lot=)
cemregoksu
and one more question:what if i want to use a dictionary instead of a list? how can i handle this?
cemregoksu
i just found a keyedcollection<key,value> and now trying it.i hope it works=)t
cemregoksu
well, key field of keyedcollection seems readonly-- so i still need help=)
cemregoksu
A: 

Please take a look at the following answer:

http://stackoverflow.com/questions/2763807/c-entity-framework-and-refreshing-listbox-after-insert

Stephen
since i am using wpf, not winforms, it was not such helpful. thanks for your help=)
cemregoksu
A: 

Implementing an observable dictionary is hard. It's much simpler to maintain an parallel observable collection, one that contains the dictionary's values. Bind the view to that collection, and make sure that any code which adds or removes values to/from the dictionary updates the both the dictionary and the parallel collection.

If you really wanted to go crazy, you could implement a subclass of ObservableCollection to hold your objects, and make that class maintain the dictionary, e.g.:

public class KeyedObject
{
    public string Key { get; set; }
    public object Value { get; set; }
}

public class ObservableMappedCollection : ObservableCollection<KeyedObject>
{
    private Dictionary<string, KeyedObject> _Map;

    public ObservableMappedCollection(Dictionary<string, KeyedObject> map)
    {
        _Map = map;    
    }

    protected override void InsertItem(int index, KeyedObject item)
    {
        base.InsertItem(index, item);
        _Map[item.Key] = item;
    }

    protected override void RemoveItem(int index)
    {
        KeyedObject item = base[index];
        base.RemoveItem(index);
        _Map.Remove(item.Key);
    }

    protected override void ClearItems()
    {
        base.ClearItems();
        _Map.Clear();
    }

    protected override void SetItem(int index, KeyedObject item)
    {
        KeyedObject oldItem = base[index];
        _Map.Remove(oldItem.Key);
        base.SetItem(index, item);
        _Map[item.Key] = item;
    }
}

There are a bunch of potential problems in the above, mostly having to do with duplicate key values. For instance, what should SetItem do if you're adding an object whose key is already in the map? The answer really depends on your application. Issues like that also hint at why there isn't an observable dictionary class in the framework.

Robert Rossney