Je suis en train d'examiner l'initialisation des membres de types génériques déclarés en XAML. Ceci cible le (reduced) generics support dans WPF 4 et le futur Silverlight. (Je l'ai essayé les scénarios ci-dessous à l'aide x:TypeArguments
et XamlReader.Load
dans VS2010 Beta 2, mais utilisera TestClassInt32 : TestClass<int> { }
pour simplifier, car il a le même comportement que directement en utilisant le type générique, mais il est plus facile à tester en utilisant compilé XAML aujourd'hui.)TypeConverter pour le type générique utilisé dans xaml
Voici les types de tests que j'utilise.
public class TestClass<T> {
[TypeConverter(typeof(StringListToItemsConverter))]
public IEnumerable<T> Items { get; set; }
public TestProperty<T> Property { get; set; }
}
[TypeConverter(typeof(TestPropertyConverter))]
public struct TestProperty<T> {
public TestProperty(T value) : this() { Value = value; }
public T Value { get; }
}
Voici l'exemple de scénario.
<StackPanel>
<StackPanel.DataContext>
<test:TestClassInt32 Items="1,2,3" Property="6" />
</StackPanel.DataContext>
<TextBox Text="{Binding Property.Value}" />
<ItemsControl ItemsSource="{Binding Items}" />
</StackPanel>
Quand je coder en dur typeof(int)
dans les convertisseurs pour cet exemple, tout fonctionne bien, mais cette approche ne fonctionne évidemment pas TestClass<double>
ou TestClass<DateTime>
. Le problème est que la méthode TypeConverter.ConvertFrom
n'a pas accès au type de destination, seul le type de source. (Ce ne fut pas un problème quand TypeConverter
a été créé dans .NET 1.0, car le type de destination ne peut pas être paramétrés, mais est une limitation malheureuse maintenant.)
Voici les démarches que je l'ai regardé pour se déplacer ce problème:
- Rendre le convertisseur de type générique; par exemple.
[TypeConverter(typeof(TestPropertyConverter<T>))]
- .NET ne prend pas en charge les paramètres de type dans les attributs
- ont le
TypeConverter
retourner un type intermédiaire qui soit met en oeuvreIConvertible.ToType
ou has aTypeConvert
that canConvertTo
the destination type - analyseur XAML ne fait que les conversions en une seule étape: si l'objet retourné ne peut pas être affecté à la destination, il jette une exception
- Définir un descripteur de type personnalisé qui renverra le convertisseur approprié en fonction du type réel
- WPF ne tient pas compte des descripteurs de type personnalisé, et
TypeDescriptor
n'existe même pas dans Silverlight
Voici les alternatives que je suis venu avec pour « travailler autour de » ce numéro:
- Exiger le type de destination à incorporer dans la chaîne; par exemple.
"sys:Double 1,2,3"
- Dans Silverlight, doivent coder en dur un ensemble fixe de types pris en charge (en WPF, peut utiliser l'interface
IXamlTypeResolver
pour obtenir le type réel qui"sys:Double"
correspond à) - Ecrire une extension de balisage personnalisé qui prend paramètre de type; par exemple.
"{List Type={x:Type sys:Double}, Values=1,2,3}"
- Silverlight ne prend pas en charge les extensions personnalisées de balisage (il ne supporte pas l'extension de balisage
x:Type
, mais vous pouvez utiliser l'approche codée en dur de l'option 1) - Créer un type d'emballage qui prend un paramètre de type et réémergentes définit tous les membres génériques comme
object
, en transmettant tous les accès membres à l'objet sous-jacent fortement typé - Possible, mais en fait une expérience utilisateur très médiocre (doit être castée pour obtenir un objet générique sous-jacent, doit toujours utiliser un codage en dur) liste pour le paramètre de type sur Silverlight, doit mettre en cache des assignations de membre jusqu'à ce que l'argument de type soit assigné, etc., etc, perd généralement la plupart des avantages de typage fort avec des génériques)
- Dans Silverlight, doivent coder en dur un ensemble fixe de types pris en charge (en WPF, peut utiliser l'interface
serait heureux d'entendre d'autres idées pour contourner ce problème aujourd'hui, ou WPF 4.
Ouais, bien sûr, vous pouvez avoir plus impressionnant ... mais pas pour 4 mois. Je ne peux pas attendre .Net 4. –
J'avais testé le service 'IProvideValueTarget' plus tôt dans VS2008, mais' TargetObject' et 'TargetProperty' renvoyaient toujours' null' (et le gros "ce type est utilisé en interne" dans le la documentation m'a amené à croire qu'il n'était pas utilisable). Je les ai re-testé dans VS2010/.NET 4 tout à l'heure et les deux ont retourné des résultats utiles. Je vous remercie! –
J'ai ajouté des informations et un exemple de code sur la façon d'obtenir le fournisseur de services qui manquait. Si je dis quelque chose d'incorrect ici, n'hésitez pas à revenir en arrière. –