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, или сначала определив ключи как ресурс:
<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}}"/>
Вы не можете опустить 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
, прежде чем вместо этого добавить значение во внутренний словарь (это может вызвать проблемы с определенными типами).
Поскольку сам словарь набирается, привязка должна не требовать приведение.
<ContentControl Content="{Binding [0], Source={StaticResource dict}}" />