Définir la valeur sur null dans la liaison WPF

116

jetez un œil à la ligne suivante

<TextBox Text="{Binding Price}"/>

Cette propriété Price ci-dessus est un Decimal?(nombre décimal nul).

Je veux que si l'utilisateur supprime le contenu de la zone de texte (c'est-à-dire entre une chaîne vide, il doit automatiquement mettre à jour la source avec null (Rien dans VB).

Des idées sur la façon dont je peux le faire «Xamly»?

Shimmy Weitzhandler
la source

Réponses:

226

J'utilise .NET 3.5 SP1 donc c'est très simple:

<TextBox Text="{Binding Price, TargetNullValue=''}"/>

Ce qui signifie (merci Gregor pour votre commentaire):

<TextBox Text="{Binding Price, TargetNullValue={x:Static sys:String.Empty}}"/>

sysest l'espace de noms XML importé pour Systemdans mscorlib:

xmlns:sys="clr-namespace:System;assembly=mscorlib"

J'espère que cela a aidé.

Shimmy Weitzhandler
la source
13
En fait, TargetNullValue fonctionne très bien. Ce qu'il fait, c'est définir une équivalence entre la valeur donnée et null. Donc, dans ce cas, lorsque la valeur liée est nulle, elle affichera une chaîne vide et lorsque la valeur de la cible est la chaîne vide, elle définira la valeur liée sur null.
Bryan Anderson
4
TargetNullValue fonctionne. J'ai obtenu les mêmes résultats lors de l'utilisation du convertisseur de valeur. Vous pouvez également simplifier l'expression: <TextBox Text = "{Binding Price, TargetNullValue = ''}" />
Gregor Slavec
2
Je suis confus - l'OP dit: "..il devrait automatiquement mettre à jour la source avec null [lorsque Target est une chaîne vide].", Mais TargetNullValue met à jour la cible , pas la source !
markmnl
1
Vous n'êtes pas le seul confus - il y a aussi des commentaires confus sur l'autre réponse. L'OP est également légèrement confus, quand il dit mettre à jour la source, il signifie en fait que la cible dans WPF parle (la source est la propriété Text sur TextBox). TargetNullValue indique la valeur sur laquelle définir la source lorsque la cible est nulle. L'inverse, dont nous tirons parti ici, est que lorsque la source est mise à jour à cette valeur spécifiée, la cible sera définie sur null.
Nathan Phillips
@markmnl Bien que TargetNullValue soit en effet destiné à mettre à jour le Targetet non le Source, cette solution fait toujours l'affaire pour une raison quelconque (je ne pouvais pas tout à fait comprendre pourquoi).
Tim Pohlmann
12

Ce convertisseur de valeur devrait faire l'affaire:

public class StringToNullableDecimalConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, 
        CultureInfo culture)
    {
        decimal? d = (decimal?)value;
        if (d.HasValue)
            return d.Value.ToString(culture);
        else
            return String.Empty;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        string s = (string)value;
        if (String.IsNullOrEmpty(s))
            return null;
        else
            return (decimal?)decimal.Parse(s, culture);
    }
}

Déclarez une instance de ce convertisseur dans les ressources:

<Window.Resources>
    <local:StringToNullableDecimalConverter x:Key="nullDecimalConv"/>
</Window.Resources>

Et utilisez-le dans votre reliure:

<TextBox Text="{Binding Price, Converter={StaticResource nullDecimalConv}}"/>

Notez que ce TargetNullValuen'est pas approprié ici: il est utilisé pour définir la valeur à utiliser lorsque le sourcede la liaison est nul. Ici, ce Pricen'est pas la source, c'est une propriété de la source ...

Thomas Levesque
la source
2
Un convertisseur est le moyen approprié de le faire, et vous ne pouvez pas définir ces convertisseurs en XAML. Les convertisseurs vous permettent de modifier le comportement de conversion "objet en objet" par défaut dans la liaison de données, ce que vous souhaitez faire.
Will Eddins
Le problème dans mon cas est que j'utilise déjà ici un convertisseur qui fait autre chose. J'ai posté une réponse, veuillez jeter un œil.
Shimmy Weitzhandler
peut vouloir utiliser IsNullOrWhiteSpace () pour permettre à "" d'être compté comme nul (très probablement ce que vous voulez)
Simon_Weaver
+1 Cependant: le prix est votre source ici mais vous avez raison TargetNullValue n'est pas approprié ici - TargetNullValue définit la cible lorsque la source est nulle - alors que nous voulons définir la source (à null) lorsque la cible est une certaine valeur (un vide string) - ce que fait votre convertisseur.
markmnl
5

Vous pouvez essayer d'utiliser un ValueConverter (IValueConverter) http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

De l'arrière de ma tête ici, quelque chose comme:

public class DoubleConverter : IValueConverter
{
    public object Convert(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
        return (double)value;
    }

    public object ConvertBack(object value, Type targetType, 
        object parameter, CultureInfo culture)
    {
    var doubleValue = Convert.ToDouble(value);

    return (doubleValue == 0 ? null : doubleValue);
    }
}

(Peut-être besoin de quelques ajustements cependant)

TimothyP
la source
Je préférerais un moyen Xamly, mais je ne peux penser à rien
Shimmy Weitzhandler