通过输入键绑定到字典值非常简单:
<TextBox Text="{Binding SomeDictionary[someKey]}" />
但是条目必须存在:
public Dictionary<string, string> SomeDictionary { get; } = new Dictionary<string, string>
{
{ "someKey", "someValue" },
};
否则(例如空字典)抛出异常:
System.Windows.Data错误:17:无法从'SomeDictionary'获取'Item []'值(类型'String')(类型'Dictionary~2')。 BindingExpression:路径= SomeDictionary [someKey]; DataItem ='MainWindow'(Name =''); target元素是'TextBox'(Name =''); target属性是'Text'(类型'String')TargetInvocationException:'System.Reflection.TargetInvocationException:调用目标抛出了异常。 ---&GT; System.Collections.Generic.KeyNotFoundException:给定的键不在字典中。 在System.Collections.Generic.Dictionary`2.get_Item(TKey key)
有没有办法自动添加带有绑定键而不是异常指定的默认值的条目?
目前,如果在代码中完成绑定,则可以实现此目的:
if (!SomeDictionary.ContainsKey("someKey"))
SomeDictionary.Add("someKey", "defaultValue");
textBox.SetBinding(TextBox.TextProperty, new Binding("[someKey]") { Source = SomeDictionary });
我正在寻找可重复使用的xaml解决方案。
我在考虑的事情:
Binding
来做某事,但到底是什么?也许有一种更简单的方法?
答案 0 :(得分:0)
可能的解决方法是将字典包装到DynamicObject
,这将允许拦截绑定调用getter / setter:
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;
}
...
}
然后使用它
public Wrapper<string> WrapperProperty { get; } = new Wrapper<string>(new Dictionary<string, string>
{
//{ "someKey", "someValue" }, // no problems if commented
});
xaml中的绑定变为{Binding WrapperProperty.someKey}
。
奖励:INotifyPropertyChanged
(未在代码中实现)使字典条目可观察,允许将多个元素绑定到相同的条目。