1
votes

Quels sont les avantages de l'utilisation de convertisseurs de valeur en XAML?

Quels sont les avantages de l'utilisation de convertisseurs de valeur en XAML? Pourquoi ne pas demander aux modèles de vue de fournir des valeurs correctes aux vues en premier lieu sans qu'il soit nécessaire de les convertir?


2 commentaires

Vous pouvez fournir un cas qui n'en profite pas dans votre cas d'utilisation, ou cette question est trop large.


Vous allez donc copier / coller la même fonction de conversion dans chaque viewmodel que vous avez?


3 Réponses :


1
votes

Ma réponse est que le convertisseur de valeur peut être réutilisé

Vous avez de nombreux contrôles dans le xaml ont besoin de la même logique de conversion, et les contrôles ont leur propre modèle de vue, vous devrez écrire le même code encore et encore


0 commentaires

1
votes

Il existe de nombreux scénarios.

Les convertisseurs peuvent changer les données d'un type à un autre, traduire des données basées sur des informations culturelles ou modifier d'autres aspects de la présentation.

Voici ce que vous pouvez lire à ce sujet sur Microsoft Docs: Conversion de données

Voici quelques scénarios typiques dans lesquels il est judicieux d'implémenter un convertisseur de données:

  • Vos données doivent être affichées différemment, selon la culture. Pour exemple, vous souhaiterez peut-être implémenter un convertisseur de devises ou un convertisseur date / heure de calendrier basé sur les conventions utilisées dans un culture particulière.

  • Les données utilisées ne sont pas nécessairement destinées à modifier le texte valeur d'une propriété, mais est plutôt destiné à changer une autre valeur, telle que la source d'une image, ou la couleur ou le style de afficher le texte. Les convertisseurs peuvent être utilisés dans ce cas en convertissant la liaison d'une propriété qui pourrait ne pas sembler appropriée, telle comme liant un champ de texte à la propriété Background d'une cellule de tableau.

  • Plus d'un contrôle ou plusieurs propriétés de contrôles sont liés à les mêmes données. Dans ce cas, la liaison principale peut simplement afficher le texte, alors que d'autres liaisons gèrent des problèmes d'affichage spécifiques mais utilisent toujours la même liaison que les informations source.

  • Une propriété cible a une collection de liaisons, qui est appelée MultiBinding. Pour MultiBinding, vous utilisez un IMultiValueConverter personnalisé pour produire une valeur finale à partir des valeurs des liaisons. Pour Par exemple, la couleur peut être calculée à partir des valeurs rouge, bleu et vert, qui peuvent être des valeurs provenant de la même source de liaison ou d'une source différente objets. Voir MultiBinding pour des exemples et des informations.

Votre question: "Pourquoi les viewmodels ne fournissent-ils pas des valeurs correctes aux vues en premier lieu sans qu'il soit nécessaire de les convertir?"

Le modèle de vue ne doit pas traiter des détails de présentation tels que la logique ou l'apparence de l'interface utilisateur. Sinon, la séparation ou le couplage lâche entre la vue et le modèle de vue n'est plus donné. Le modèle de vue présente uniquement les données requises pour un contexte spécifique (ou des user stories). Il ne connaît pas les contraintes de conception liées à la vue, telles que la coloration ou les états visuels. Par exemple, si vous souhaitez représenter des données en tant qu'état visuel d'un contrôle, vous devez convertir la valeur des données, par exemple. à une couleur ou Visibilité . Les convertisseurs de valeur aident à maintenir le couplage lâche entre la vue et le modèle de vue.


0 commentaires

1
votes

Pour beaucoup de choses, vous avez raison et ce n'est pas "mal" pour un viewmodel de faire la traduction. Il est souvent plus pratique de le faire dans un viewmodel ou lors de la copie de données d'un modèle dans un viewmodel.

Un viewmodel peut utiliser une classe injectée qui fournit un comportement réutilisable. Par conséquent, la simple réutilisation n'est pas propre aux convertisseurs.

Ce n'est pas un "acquis" qu'un convertisseur est toujours la chose à choisir.

Un convertisseur vit dans la couche View et donc dans un projet qui aura déjà des références pour visualiser les visuels, les contrôles, l'énumération. Lorsque vous souhaitez renvoyer Visibility.Hidden, cette énumération se trouve dans System.Windows. Si votre viewmodel est dans une bibliothèque de classes, il n'aura pas du tout de référence à cette DLL. De même avec les pinceaux, les couleurs, etc. Peut-être que vous n'avez pas de grandes solutions, donc vos modèles de vue sont toujours dans le même exe que vos vues et par conséquent cette référence n'a pas d'importance.

Ce n'est pas vraiment un avantage ici.

Si vous avez un convertisseur comme ressource d'application, il n'y en aura qu'une seule instance. (Sauf si vous faites quelque chose comme set x: Shared false.)

En supposant que vous fusionniez le dictionnaire de ressources qui crée l'instance dans app.xaml. Ce n'est souvent ni ici ni là du point de vue de la mémoire, mais vous pouvez l'ajuster afin d'avoir une instance par utilisation ou par portée (comme une fenêtre) ou par application.

Un modèle de vue peut avoir un objet qui est une classe statique ou d'instance. Il existe un cas d'utilisation très spécifique où la différence pourrait être significative.

Peut-être que vous voulez "vraiment" simplement convertir une propriété en quelque chose qui n'est pas un modèle de vue. Vous pouvez le lier à une propriété ou simplement aller directement avec un convertisseur. Là encore, ce n'est pas un énorme avantage.

Vous pouvez créer un convertisseur (également) une extension de balisage personnalisée:

http://drwpf.com/blog/2009/03/17/ trucs-et-astuces-rendant-les-convertisseurs-de-valeur-plus-accessibles-dans-le-balisage /

public class DummyConverter : MarkupExtension, IValueConverter
{
    private static DummyConverter _converter = null;
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_converter == null)
        {
            _converter = new DummyConverter();
        }
        return _converter;
    }

Ce qui précède vous donnera une seule instance du comportement sous-jacent comme le ferait un convertisseur comme le ferait une ressource. Alternativement, vous pouvez simplement renvoyer "this" et avoir une instance par utilisation. Puisqu'il s'agit d'une extension de balisage, vous pouvez ajouter des propriétés définies dans xaml pour transmettre des paramètres fixes.

Cela signifie que vous pouvez encapsuler le comportement résultant de plusieurs propriétés dans un seul morceau de code.

Imaginez un instance où vous avez besoin d'une référence à quelque chose dans la vue. C'est peut-être la fenêtre. Mais votre liaison est dans un certain contrôle de l'utilisateur. Vous pouvez utiliser un multibinding et un multiconverter pour aller chercher une référence sur la largeur, la hauteur, l'arrière-plan de la fenêtre ... tout ce que vous voulez. Le convertisseur peut ensuite traduire n'importe quel nombre de propriétés hors des éléments de vue et faire tout ce dont vous avez besoin avec cela. Tout dans la vue. Le viewmodel n'a pas besoin de savoir ce qu'est une fenêtre pour que cela fonctionne.

Ce qui est élégant et similaire.

Peut-être plus important encore, vous pouvez toujours effectuer des tests unitaires sur votre modèle de vue en tant qu'instance discrète s'il n'a pas besoin d'une vue instanciée pour fonctionner.

La lisibilité et la flexibilité sont des avantages potentiels.

Supposons que vous vouliez plusieurs valeurs basées sur une propriété. Vous pouvez ajouter une propriété par variante à votre modèle de vue. Cela deviendra assez maladroit assez rapidement et vous changez le code dans un modèle de vue et vous l'utilisez dans une vue.

Je vais vous donner un exemple concret ici.

Dans le wargame sur lequel je travaille, il y a des unités. Chacun contient un ou plusieurs symboles de l'OTAN qui sont rectangulaires avec diverses croix, ellipses, etc. La taille d'une unité est quelque chose qu'un concepteur de scénario peut contrôler. Par conséquent, la taille est liée. La largeur et la hauteur de chaque symbole sont une proportion de la taille de l'unité. Lorsque vous avez 2 symboles de ce type (le nombre indique la force 1-4), la largeur et la hauteur sont une proportion et l'écart entre les autres. Si vous regardiez le balisage pour chacun, vous verriez de nombreuses instances d'un convertisseur multiplicateur. Chacun a un paramètre multiplicateur. Cela pourrait être 0,35, 0,02, 0,16 fois la taille de la pièce. La taille a une valeur de repli afin que vous puissiez voir une unité dans le concepteur. En construisant cela, je pouvais facilement changer chaque multiplicateur pour vérifier à quoi ressemblaient les choses. Cela aurait été beaucoup moins pratique de le faire dans le viewmodel.


5 commentaires

Êtes-vous vraiment en train de dire que les deux grands avantages d'une implémentation de convertisseur autonome par rapport à une conversion à l'intérieur du modèle de vue sont que l'instance de convertisseur est réutilisée dans la portée du ResourceDictionary parent (lorsqu'elle est déclarée à l'intérieur d'un < code> ResourceDictionary et l'attribut x: Shared défini sur true )? Et que vous pouvez créer une classe qui étend MarkupExtension et implémente IValueConverter ? "Les convertisseurs ont également une propriété de paramètre de conversion pouvant être liée." n'est pas vrai. ConverterParameter est une propriété de Binding et ne peut pas être lié car il ne s'agit pas d'un DependencyProperty .


Non, je ne suis pas. Un convertisseur régulier n'a pas du tout besoin de cet ensemble d'attributs pour être un singleton. Je pensais avoir supprimé cette partie concernant la liaison du paramètre. Remerciements fixes.


Non, cet attribut est implicitement défini sur true par défaut. Je voulais juste préciser que ce n'est pas la règle, mais dépend plutôt de la déclaration du convertisseur. Singleton est un modèle de conception qui garantit qu'une instance statique ne peut exister qu'une seule fois dans la portée statique. L'analyseur XAML ne suit pas ce modèle. L'instance créée n'est pas statique et ce n'est pas une seule instance. L'analyseur réutilise une seule instance dans la portée actuelle (lorsque x: Shared = "True" ). Comme il peut y avoir plusieurs étendues, il peut également y avoir plusieurs instances de l'objet de ressource. Aucune offense, je dis juste.


Hum ... Je pensais avoir couvert l'aspect de la portée assez clairement. Peut être pas.


Vous avez mal utilisé le terme Singleton dans ce contexte.