Implémentation asynchrone d'IValueConverter
Si une Méthode asynchrone qui je veux déclencher à l'intérieur d'un IValueConverter.
Est-il mieux d'Attendre, puis la forçant à être synchrone en appelant le résultat de la Propriété?
public async Task<object> Convert(object value, Type targetType, object parameter, string language)
{
StorageFile file = value as StorageFile;
if (file != null)
{
var image = ImageEx.ImageFromFile(file).Result;
return image;
}
else
{
throw new InvalidOperationException("invalid parameter");
}
}
Vous devez vous connecter pour publier un commentaire.
Vous ne voulez probablement pas à appeler
Task.Result
, pour un couple de raisons.Tout d'abord, comme je l'explique en détail sur mon blog, vous pouvez impasse à moins que votre
async
code a été écrit à l'aideConfigureAwait
partout. Deuxièmement, vous ne voulez probablement pas à (de façon synchrone) bloquer votre INTERFACE utilisateur; il serait préférable d'afficher temporairement un "chargement..." ou vide de l'image lors de la lecture à partir du disque, et de mettre à jour une fois la lecture terminée.Donc, personnellement, je voudrais faire cette partie de mon ViewModel, pas un convertisseur de valeurs. J'ai un blog décrivant certains la liaison de données-amicale des façons de faire initialisation asynchrone. Ce serait mon premier choix. Il juste ne se sent pas le droit d'avoir un valeur convertisseur le coup d'envoi asynchrone opérations d'arrière-plan.
Toutefois, si vous avez considéré comme votre conception et de vraiment réfléchir asynchrone valeur convertisseur est ce que vous avez besoin, alors vous devez obtenir un peu plus créatif. Le problème avec les convertisseurs de valeur, c'est qu'ils ont synchrone: la liaison de données commence au contexte de données, d'évaluer le chemin d'accès, puis invoque une valeur de conversion. Seul le contexte de données et le chemin de soutien des notifications de changement.
Donc, vous devez utiliser un (synchrone) convertisseur de valeurs dans votre contexte de données pour convertir votre valeur d'origine dans une liaison de données-friendly
Task
-comme l'objet et ensuite votre propriété de liaison utilise l'une des propriétés de laTask
-comme l'objet pour obtenir le résultat.Voici un exemple de ce que je veux dire:
La
TextBox
est juste une zone de saisie. LeTextBlock
définit d'abord son propreDataContext
à laTextBox
's saisie de texte en cours d'exécution à travers un "asynchrone" convertisseur.TextBlock.Text
est définie à l'Result
de ce convertisseur.Le convertisseur est assez simple:
Le convertisseur démarre pour la première fois une opération asynchrone à attendre 5 secondes, puis ajouter " fait!" à la fin de la chaîne d'entrée. Le résultat de ce que le convertisseur ne peut pas être juste une plaine
Task
parce queTask
ne pas mettre en œuvreIPropertyNotifyChanged
, donc je suis en utilisant un type qui sera dans la prochaine version de mon AsyncEx bibliothèque. Il ressemble à quelque chose comme ceci (simplifié pour cet exemple; source complet est disponible):En mettant ces pièces ensemble, nous avons créé une transmission de données asynchrones contexte qui est le résultat d'un convertisseur de valeurs. Le databinding-friendly
Task
wrapper suffit d'utiliser le résultat par défaut (généralementnull
ou0
) jusqu'à ce que leTask
complète. Si l'emballage estResult
est assez différent deTask.Result
: il ne sera pas de façon synchrone bloc et il n'y a pas de danger de blocage.Mais je le répète: j'ai choisi de mettre en logique asynchrone dans le ViewModel plutôt qu'une valeur convertisseur.
MarkupExtension
et pourquoiProvideValue
renvoie lui-même?ITaskCompletionNotifier
? Je ne vois pas la définition de votre réponse, n'importe où.ITaskCompletionNotifier<T>
qui dérive deITaskCompletionNotifier
. Voir mon MSDN article sur async liaison de données pour un exemple plus complet.MarkupConverter
/IValueConverter
wrapper est assez WPF spécifiques et ne fonctionne que sur Xamarin si ils ont les mêmes types.