1

鉴于:

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在这里找到的

TextBox 绑定到集合项之一(继承 DataContext):

<TextBox Text="{Binding Params[APN_HOST].Value}"/>

当我手动将“APN_HOST”项添加到集合中时,绑定按预期工作。

现在,我被困在哪里:我希望能够以这种方式编辑一个空集合,即,

如果集合中没有具有指定键的项目,并且用户在文本框中键入了一些文本,则会导致将新项目添加到具有相应键的集合中。

我试图在集合中实现某种“如果未找到则默认”语义,但它导致所有文本框都绑定到相同的默认实例StringRecord,共享单个值:)

感觉就像我在这里忽略了一些非常明显的东西。

4

1 回答 1

0

嗯,那是一个非常艰难的!

我所做的是:

ObservableKeyedCollection1 ) 扩展

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,绑定引擎正确地解析它。
  • 如果提供了 new-item-delegate,我们利用它来获取缺失键的一些默认项目实例。此新项目不会立即添加到集合中,因为它可能违反仅在用户实际编辑值后才添加值的要求。反而,
  • 如果项目实现了INotifyPropertyChanged,我们挂钩它的PropertyChanged事件,将项目从处理程序添加到集合中并立即取消订阅PropertyChanged

仅此一项就足够了,但是……出于某种奇怪的原因,嵌套属性通知不会触发!

2)重写绑定如下:

<TextBox DataContext="{Binding Params[APN_HOST]}" Text="{Binding Value}" />

现在它触发了,触发了上述机制!

编辑。在这里进行了一些讨论之后,我现在看到第二次修改是解决方案中不可避免的一部分,因为默认行为。根本没有其他可能性可以确定哪个实例已更改。

于 2012-06-10T03:51:10.300 回答