2012-02-25 10 views
10

Czy istnieje sposób dodania elementu SortedList lub Dictionary do zasobu ResourceDictionary i użycia (i powiązania!) Z formantem za pośrednictwem XAML?Dodawanie listy SortedList lub Dictionary <int, string> do ResourceDictionary

Próbowałem, ale nie mogłem dowiedzieć się, jak to zrobić:

<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

'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]'. –

+0

@SeToY, proszę odpowiedzieć na pytanie. – Shimmy

+0

@Shimmy To był środek nocy tutaj i poszedłem spać ;-) – SeToY

Odpowiedz

16

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}}" /> 
+0

Dziękuję za tę wspaniałą odpowiedź, to bardzo mi pomogło :) – SeToY

+0

@SeToY: Nie ma za co, pomyślałem, że to interesujące pytanie. –

+0

@ H.B. btw: gratulacje na 40k –