At the moment I'm writing my own dictionary that implements INotifyPropertyChanged. See below:
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
new public Item this[TKey key]
{
get { return base.Item[key]; }
set(TValue value)
{
if (base.Item[key] != value)
{
base.Item[key] = value;
OnPropertyChanged("XXX"); // what string should I use?
}
}
}
My goal is simple: when a certain value in the Dictionary has changed, notify that it has changed. All WPF elements that have a binding with the corresponding key name should then update themselves.
Now my question is: what string should I use as propertyName
in order to notify?
I have tried "[" + key.ToString() + "]"
, "Item[" + key.ToString() + "]"
and simply key.ToString()
. They all did not seem to work, because the WPF elements did not update.
Using String.Empty
(""
) does update the WPF elements, but I'm not using this, because this will update all WPF elements that are bound the same dictionary, even though they have different keys.
This is how my binding looks like in XAML:
<TextBlock DataContext="{Binding Dictionary}" Text="{Binding [Index]}" />
Index
is of course the name of the key in my dictionary.
In stead of using INotifyPropertyChanged, some have suggested to use INotifyCollectionChanged. I tried this:
Dim index As Integer = MyBase.Keys.ToList().IndexOf(key)
Dim changedItem As Object = MyBase.ToList().ElementAt(index)
RaiseEvent CollectionChanged(Me, New NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, changedItem, index))
But that does not update the bound WPF elements either.
Perhaps you need to consider the INotifyCollectionChanged interface rather than INotifyPropertyChanged
. If that's the case, have a look at this question and the blog post that it links to.
Also, check this answer to a previous question that was similar to yours. It suggests that you use the value of Binding.IndexerName as the property name for the change notification.
Edit:
If you want to avoid using INotifyCollectionChanged
, you might try an alternative approach. Change your dictionary so that the type of its values is a proxy object that implements INotifyPropertyChanged
.
public class MyProxy<T> : INotifyPropertyChanged
{
public T Value
{
// Getter and setter with change notification code here.
}
}
Then insert instances of this type into your dictionary just once. Replace the code that updates a value in the dictionary with code that retrieves the proxy, then updates its Value
property.
You would need to change your XAML binding to something like ([Item]).Value
.
After reviewing some of your other comments, it does look as though this approach might work for you. It's similar to something I had to do recently. Create a custom KeyedCollection and a corresponding proxy. Add a ItemName
property to the proxy; it can be read only, and does not need to support change notifications. Make your KeyedCollection
implementation index on the ItemName
property. Works a treat! I'll add sample code if you would like it.
if (base.Item[key] != value)
{
base.Item[key] = value;
if (key == "notifykey") OnPropertyChanged("[Item]");
}
String.empty will notify all properties not just Item
Per op this as the problem of all the bindings to Dictionary still update.
So I would make a new property
Let just assume you value is string Bind to KeyedValue
public String KeyedValue
{
get { return base.Item[Index]; }
}
if (key == "Index") OnPropertyChanged("KeyedValue");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With