I have a BindingProxy to Bind the Visibility-Property of DataGridColumns of a DataGrid to a Value in a Dictionary (\"ColumnsVisibility\"). I Also have a Context-Menu, that s
EDIT:
It is an error for sure:
PropertyChanged(
null, new PropertyChangedEventArgs("ColumnsVisibility"));
It should be:
PropertyChanged(
this, new PropertyChangedEventArgs("ColumnsVisibility"));
I have blindly copied it into my first edit from your code. Well, sometimes you just don't see the things before your eyes
For future I recommend you to use some sort of a function in some base class like
public class NotifyPropertyChangeableBase: INotifyPropertyChanged // Usually I name it somewhat like 'ViewModelBase' in my projects, but your actual class is the control, so it is not the most appropriate name
{
protected void OnPropertyChanged(String propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
It did not solve the issue, but it is at least one problem down
EDIT WITH(I HOPE) THE FINAL SOLUTION:
It looks that you cannot notify the WPF engine that your dictionary has changed its items. And standard Dictionary does not do it on its own(it does not implement the ICollectionChanged or even INotifyPropertyChanged).
That's why you have to use your own dictionary, or to be more precise wrapper dictionary class:
public class DictionaryNotificationWrapper<TKey, TValue> : IDictionary<TKey, TValue>, INotifyPropertyChanged
{
#region Fields
private IDictionary<TKey, TValue> innerDictionary;
#endregion
#region Constructors
public DictionaryNotificationWrapper(IDictionary<TKey, TValue> innerDictionary)
{
if (innerDictionary == null)
throw new ArgumentNullException("innerDictionary", "The inner dictionary is null");
this.innerDictionary = innerDictionary;
}
#endregion
#region IDictionary implementation
public TValue this[TKey key]
{
get
{
return this.innerDictionary[key];
}
set
{
this.innerDictionary[key] = value;
this.OnPropertyChanged("Item[]");
this.OnPropertyChanged("Count");
}
}
#endregion
#region not implemented IDictionary members - you are free to finish the work
public void Add(TKey key, TValue value)
{
throw new NotImplementedException();
}
public bool ContainsKey(TKey key)
{
throw new NotImplementedException();
}
public ICollection<TKey> Keys
{
get { throw new NotImplementedException(); }
}
public bool Remove(TKey key)
{
throw new NotImplementedException();
}
public bool TryGetValue(TKey key, out TValue value)
{
throw new NotImplementedException();
}
public ICollection<TValue> Values
{
get { throw new NotImplementedException(); }
}
public void Add(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public void Clear()
{
throw new NotImplementedException();
}
public bool Contains(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int Count
{
get { throw new NotImplementedException(); }
}
public bool IsReadOnly
{
get { throw new NotImplementedException(); }
}
public bool Remove(KeyValuePair<TKey, TValue> item)
{
throw new NotImplementedException();
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
throw new NotImplementedException();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
#endregion
#region INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(String propertyName)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
#endregion
}
With such a class:
/// <summary>
/// Interaction logic for HyperVControl.xaml
/// </summary>
public partial class HyperVControl : UserControl, INotifyPropertyChanged
{
#region Constructors
public HyperVControl()
{
// Form initialization
InitializeComponent();
// Initialize columns visibility collection
IDictionary<String, Boolean> innerColumnsVisibilityDictionary = new Dictionary<String, Boolean>();
innerColumnsVisibilityDictionary.Add("ElementName", true);
// Wrap the visibility dictionary
this.ColumnsVisibility = new DictionaryNotificationWrapper<String, Boolean>(innerColumnsVisibilityDictionary);
// Initialize grid's datasource
this.HVMachineList = new ObservableCollection<HyperVMachine>();
this.HVMachineList.Add(new HyperVMachine());
this.HVMachineList.Add(new HyperVMachine());
this.HVMachineList.Add(new HyperVMachine());
}
you will be able to notify your visual components without any code-behind.
P.S.: I have implemented INotifyProperyChanged that notifies about the changes in Item[] indexed property, but you could try to implement INotifyCollectionChanged interface - I am just unsure how it will work with indexed bindings.
P.P.S.: I haven't seen your comment that you have found this.PropertyChanged(
this, new ...
issue.
P.P.P.S.: If you have time then change the question title to "BindingProxy: binding to the indexed property" to better reflect the problem and leave only the code from the last edit(to avoid duplication) - think of it as the community service.