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はコレクションアイテムの1つにバインドされます(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}" />

これで起動し、上記のメカニズムがトリガーされます。

編集。ここでいくつかの議論を行った後、デフォルトの動作のために、2番目の変更がソリューションの必然的な部分であることがわかりました。どのインスタンスが変更されたかを判断する他の可能性はありません。

于 2012-06-10T03:51:10.300 に答える