The reason that there is no ObservableKeyedCollection (or any other such type which is merely a combination of other generic types) is because ObservableCollection is generic, and that makes implementation of an "ObservableKeyedCollection" as easy as this:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
public class DictionaryWatcher : ObservableCollection<KeyValuePair<string, object>>, IDisposable
{
private NotifyCollectionChangedEventHandler watcher;
private bool watching = false;
public DictionaryWatcher()
{
watcher = new NotifyCollectionChangedEventHandler( ReportChange );
CollectionChanged += watcher;
Watched = true;
}
public bool Watched
{
get
{
return watching;
}
set
{
if (watching)
{
lock (this)
{
CollectionChanged -= watcher;
watching = false;
}
}
}
}
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize( this );
}
public void Initialize()
{
this.Add( new KeyValuePair<string, object>( "First", 1 ) );
this.Add( new KeyValuePair<string, object>( "Second", 2 ) );
this.Add( new KeyValuePair<string, object>( "Turd", 3 ) );
KeyValuePair<string, object> badValue = this[2];
this.Remove( badValue );
}
protected virtual void Dispose( bool disposing )
{
if (disposing && Watched)
{
Watched = false;
}
}
private void ReportChange( object sender, NotifyCollectionChangedEventArgs e )
{
Console.WriteLine( "Change made: {0}", e.Action );
}
}
While that is certainly not a one-liner program, most of it is boilerplate. Most importantly, it doesn't re-implement the ObservableCollection as you were suggesting; instead it fully utilizes it.
The reason that it "whouldn't be a good addition to the .NET Framework" is because when there's already one way to do something, creating another way to do it is a bad idea. The fewer ways there are to get some particular task done, the fewer ways there are to do it poorly. 8 )
The tools are provided, it's now all about how you use them.
Hope that helps!