有没有办法将SortedList或Dictionary添加到ResourceDictionary并通过XAML使用(并绑定!)它到控件?
我试过这个,但我无法弄清楚如何做到这一点:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:coll="clr-namespace:System.Collections.Generic;assembly=mscorlib">
<x:Array x:Key="test"
Type="sys:Object">
<coll:KeyValuePair>***</coll:KeyValuePair>
</x:Array>
答案 0 :(得分:18)
SortedList
很简单,因为它不是通用的。
如果类实现IDictionary
,您可以通过使用x:Key
将它们定义为子节点来添加值,以设置应将它们添加到字典中的键。
xmlns:col="clr-namespace:System.Collections;assembly=mscorlib"
<col:SortedList x:Key="list">
<sys:String x:Key="0">Lorem</sys:String>
<sys:String x:Key="1">Ipsum</sys:String>
<sys:String x:Key="2">Dolor</sys:String>
<sys:String x:Key="3">Sit</sys:String>
</col:SortedList>
<!-- Usage: -->
<ContentControl Content="{Binding [0], Source={StaticResource list}}" />
项目键是这里的字符串,为了获得实际的int,您可以使用自定义标记扩展将字符串解析为int,或者首先将键定义为资源:
<sys:Int32 x:Key="key1">0</sys:Int32>
<sys:Int32 x:Key="key2">1</sys:Int32>
<sys:Int32 x:Key="key3">2</sys:Int32>
<sys:Int32 x:Key="key4">3</sys:Int32>
<col:SortedList x:Key="list">
<sys:String x:Key="{StaticResource key1}">Lorem</sys:String>
<sys:String x:Key="{StaticResource key2}">Ipsum</sys:String>
<sys:String x:Key="{StaticResource key3}">Dolor</sys:String>
<sys:String x:Key="{StaticResource key4}">Sit</sys:String>
</col:SortedList>
然后绑定变得更加复杂,因为索引器值需要显式地转换为int,否则它将被解释为字符串。
<ContentControl Content="{Binding Path=[(sys:Int32)0],
Source={StaticResource list}}"/>
由于implementation detail,您无法省略Path=
。
字典并不那么容易,因为它们是通用的,并且(目前)没有简单的内置方法来在XAML中创建通用对象。但是,使用标记扩展可以通过反射创建通用对象。
在此类扩展上实现IDictionary
还允许您填充新创建的实例。这是一个非常粗略的示例:
public class DictionaryFactoryExtension : MarkupExtension, IDictionary
{
public Type KeyType { get; set; }
public Type ValueType { get; set; }
private IDictionary _dictionary;
private IDictionary Dictionary
{
get
{
if (_dictionary == null)
{
var type = typeof(Dictionary<,>);
var dictType = type.MakeGenericType(KeyType, ValueType);
_dictionary = (IDictionary)Activator.CreateInstance(dictType);
}
return _dictionary;
}
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return Dictionary;
}
public void Add(object key, object value)
{
if (!KeyType.IsAssignableFrom(key.GetType()))
key = TypeDescriptor.GetConverter(KeyType).ConvertFrom(key);
Dictionary.Add(key, value);
}
#region Other Interface Members
public void Clear()
{
throw new NotSupportedException();
}
public bool Contains(object key)
{
throw new NotSupportedException();
}
// <Many more members that do not matter one bit...>
#endregion
}
<me:DictionaryFactory x:Key="dict" KeyType="sys:Int32" ValueType="sys:String">
<sys:String x:Key="0">Lorem</sys:String>
<sys:String x:Key="1">Ipsum</sys:String>
<sys:String x:Key="2">Dolor</sys:String>
<sys:String x:Key="3">Sit</sys:String>
</me:DictionaryFactory>
由于传入一个类型化的实例作为键有点痛苦,我选择在将值添加到内部字典之前在IDictionary.Add
中进行转换(这可能会导致某些类型的问题)。 / p>
由于字典本身是键入的,因此不的绑定需要强制转换。
<ContentControl Content="{Binding [0], Source={StaticResource dict}}" />