假设:
class StringRecord : INotifyPropertyChanged
{
public string Key { get; set; } // real INPC implementation is omitted
public string Value { get; set; } // real INPC implementation is omitted
...
}
class Container
{
public ObservableKeyedCollection<string, StringRecord> Params { get; set; }
...
{
ObservableKeyedCollection
为the one found here。
TextBox绑定到其中一个集合项(继承DataContext):
<TextBox Text="{Binding Params[APN_HOST].Value}"/>
当我手动将“APN_HOST”项添加到集合时,绑定按预期工作。
现在,我陷入困境:我希望能够以这种方式编辑一个空集合,即
如果集合中没有带有指定键的项目,并且用户在文本框中键入了一些文本,则会导致使用相应的键将新项目添加到集合中。
我试图在集合中实现某种“默认的if not found”语义,但它导致所有文本框绑定到StringRecord
的同一默认实例,共享一个值:)
感觉我在这里忽略了一些非常明显的东西。
答案 0 :(得分:0)
嗯,这真的很难!
我所做的是:
1)使用
扩展ObservableKeyedCollection
public class ObservableKeyedCollection<TKey, TItem> : KeyedCollection<TKey, TItem>, INotifyCollectionChanged
{
...
Func<TKey,TItem> m_newItemDelegate;
public ObservableKeyedCollection(Func<TItem, TKey> getKeyForItemDelegate, Func<TKey, TItem> newItemDelegate = null)
: base()
{
...
m_newItemDelegate = newItemDelegate;
}
public new TItem this[TKey key]
{
get
{
if (m_newItemDelegate != null && !Contains(key))
{
TItem i = m_newItemDelegate(key);
var i_as_inpc = i as INotifyPropertyChanged;
if (i_as_inpc != null)
i_as_inpc.PropertyChanged += new PropertyChangedEventHandler(AddItemOnChangeHandler);
else
Add(i);
return i;
}
return base[key];
}
set
{
if (Contains(key)) Remove(key);
Add(value);
}
}
private void AddItemOnChangeHandler(object sender, PropertyChangedEventArgs e)
{
(sender as INotifyPropertyChanged).PropertyChanged -= AddItemOnChangeHandler;
Add((TItem)sender);
}
new
,但绑定引擎正确解析了它。INotifyPropertyChanged
,我们会挂钩其PropertyChanged
事件,将该项目从处理程序添加到集合中,并立即取消订阅PropertyChanged
。仅此一项就足够了,但......出于某种奇怪的原因,嵌套属性通知不会触发!
2)重写绑定如下:
<TextBox DataContext="{Binding Params[APN_HOST]}" Text="{Binding Value}" />
现在它会触发,触发上述机制!
编辑。经过一些讨论here,我现在看到第二次修改是解决方案中不可避免的一部分,因为默认行为。没有其他可能性来确定哪个实例已被更改。