SortedList
jest łatwe, gdyż nie jest nazwą rodzajową.
Jeśli klasa implementuje IDictionary
, możesz dodać wartości, definiując je jako węzły potomne, używając x:Key
, aby ustawić klucz, do którego mają zostać dodane do słownika.
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}}" />
Klucze pozycji są tu ciągi, aby uzyskać rzeczywiste ints można użyć rozszerzenia niestandardowych znaczników, które analizuje ciąg na int, lub poprzez definiowanie klawiszy jako zasobu pierwszy :
<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>
Wiązanie staje się bardziej złożone, ponieważ wartość indeksu musi być rzutowana na wartość int jawnie inaczej byłoby interpretowane jako ciąg.
<ContentControl Content="{Binding Path=[(sys:Int32)0],
Source={StaticResource list}}"/>
Ty nie może pominąć Path=
powodu implementation detail.
Słowniki nie są tak łatwe, ponieważ są one ogólne i tam (obecnie) nie jest proste wbudowane w sposób tworzyć obiekty rodzajowe w XAML. Używając rozszerzeń znaczników możesz jednak tworzyć ogólne obiekty poprzez odbicie.
Implementacja IDictionary
w takim rozszerzeniu pozwala również wypełnić nowo utworzone wystąpienie. Tutaj jest bardzo szkicowy przykład:
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>
Jak przechodzącą w wpisywanych przykład jako klucz jest trochę uciążliwe wybrałem zrobić konwersję w IDictionary.Add
przed wartością jest dodawany do słownik wewnętrzny (może to powodować problemy z niektórymi typami).
Ponieważ sam słownik jest wpisany, jego powiązanie nie powinno być wymagane od od.
<ContentControl Content="{Binding [0], Source={StaticResource dict}}" />
'x: Array' byłoby w porządku, jeśli dodać * * wartości w porządku, to po prostu dodać pierwszy' ' i byłoby uzyskać indeks' 0' i tak dalej, wiązanie to może celuj w indeksator za pomocą '[0]'. –
@SeToY, proszę odpowiedzieć na pytanie. – Shimmy
@Shimmy To był środek nocy tutaj i poszedłem spać ;-) – SeToY