2017-07-18 18 views
0

は非常に簡単です:辞書への結合、エントリーキーで辞書値にバインド自動的に不足しているエントリを作成

<TextBox Text="{Binding SomeDictionary[someKey]}" /> 

エントリー必須の存在しかし:

public Dictionary<string, string> SomeDictionary { get; } = new Dictionary<string, string> 
{ 
    { "someKey", "someValue" }, 
}; 

そうでない場合(たとえば、空の辞書用)AN例外がスローされます:

System.Windows.Data Error: 17 : Cannot get 'Item[]' value (type 'String') from 'SomeDictionary' (type 'Dictionary~2'). BindingExpression:Path=SomeDictionary[someKey]; DataItem='MainWindow' (Name=''); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') TargetInvocationException:'System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary. at System.Collections.Generic.Dictionary`2.get_Item(TKey key)

指定のデフォルト値を持つエントリを自動的に追加する方法はありますかdは例外の代わりにキーをバインドしますか?私は、再利用可能なXAMLソリューションを探しています

if (!SomeDictionary.ContainsKey("someKey")) 
    SomeDictionary.Add("someKey", "defaultValue"); 
textBox.SetBinding(TextBox.TextProperty, new Binding("[someKey]") { Source = SomeDictionary }); 

:結合は、コード内で行われている場合

は現在、これを実現することができます。

物事は私が考えています:

  • 行動(添付プロパティ)、または上記の1つのようなコードを実行するためのマークアップ拡張機能を作成します。
  • キャッチ何とか例外とまたは他に何を再バインド?
  • 何かを行うために独自のBindingを作成しますが、正確に何?

おそらく、もっと簡単な方法はありますか?

+1

変換を試しましたか?それは私がやることです。 –

+0

とデフォルト値を作成するときに "somekey"値を維持しますか? –

答えて

0

可能な回避策は、これが呼び出しゲッター/セッターを結合インターセプトにできるようになります、DynamicObjectに辞書をラップすることです。その後、

public class Wrapper<T> : DynamicObject, INotifyPropertyChanged 
{ 
    readonly Dictionary<string, T> _dictionary; 

    public Wrapper(Dictionary<string, T> dictionary) 
    { 
     _dictionary = dictionary; 
    } 

    public override bool TryGetMember(GetMemberBinder binder, out object result) 
    { 
     T value; 
     if (!_dictionary.TryGetValue(binder.Name, out value)) 
     { 
      value = default(T); 
      _dictionary.Add(binder.Name, value); 
     } 
     result = value; 
     return true; 
    } 

    public override bool TrySetMember(SetMemberBinder binder, object value) 
    { 
     _dictionary[binder.Name] = (T)value; 
     OnPropertyChanged(binder.Name); 
     return true; 
    } 

    ... 
} 

{Binding WrapperProperty.someKey}なっ

public Wrapper<string> WrapperProperty { get; } = new Wrapper<string>(new Dictionary<string, string> 
{ 
    //{ "someKey", "someValue" }, // no problems if commented 
}); 

XAMLでバインディングを使用します。

ボーナス:INotifyPropertyChanged(コードでは実装されていません)ディクショナリエントリを観察可能にし、複数の要素を同じエントリにバインドできるようにします。

関連する問題