Defina o valor como nulo na ligação WPF

116

por favor, dê uma olhada na seguinte linha

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

Esta propriedade Price de cima é um Decimal?(decimal anulável).

Eu quero que se o usuário excluir o conteúdo da caixa de texto (ou seja, inserir uma string vazia, ele deve atualizar automaticamente a fonte com nulo (Nada em VB).

Alguma ideia de como posso fazer 'Xamly'?

Shimmy Weitzhandler
fonte

Respostas:

226

Estou usando o .NET 3.5 SP1, então é muito simples:

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

Que significa (obrigado Gregor pelo seu comentário):

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

sysé o namespace xml importado para Systemem mscorlib:

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

Espero que tenha ajudado.

Shimmy Weitzhandler
fonte
13
Na verdade, TargetNullValue funciona muito bem. O que ele faz é definir uma equivalência entre o valor fornecido e nulo. Portanto, neste caso, quando o valor vinculado for nulo, ele exibirá uma string vazia e quando o valor do destino for a string vazia, ele definirá o valor vinculado como nulo.
Bryan Anderson
4
O TargetNullValue funciona. Obtive os mesmos resultados ao usar o conversor de valor. Você também pode simplificar a expressão: <TextBox Text = "{Binding Price, TargetNullValue = ''}" />
Gregor Slavec
2
Estou confuso - o OP diz: "..ele deveria atualizar automaticamente a fonte com nulo [quando o destino é uma string vazia].", Mas o TargetNullValue atualiza o destino , não a fonte !
markmnl
1
Você não é o único confuso - há comentários confusos na outra resposta também. O OP também fica um pouco confuso, quando diz atualizar o código-fonte, ele realmente quer dizer o destino no WPF speak (o código-fonte é a propriedade Text no TextBox). TargetNullValue diz qual valor definir como Source quando o Target for null. O reverso disso, que é o que estamos aproveitando aqui, é que quando a fonte for atualizada para este valor especificado, o destino será definido como nulo.
Nathan Phillips
@markmnl Embora TargetNullValue tenha de fato a intenção de atualizar o Targete não o Source, esta solução ainda funciona por algum motivo (não consegui descobrir o porquê).
Tim Pohlmann,
12

Este conversor de valor deve fazer o truque:

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);
    }
}

Declare uma instância deste conversor nos recursos:

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

E use-o em sua ligação:

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

Observe que TargetNullValuenão é apropriado aqui: ele é usado para definir qual valor deve ser usado quando o sourceda vinculação é nulo. Aqui Pricenão é a fonte, é uma propriedade da fonte ...

Thomas Levesque
fonte
2
Um conversor é a maneira adequada de fazer isso e você não pode definir esses conversores em XAML. Os conversores permitem que você altere o comportamento de conversão padrão "objeto para objeto" na vinculação de dados, que é o que você deseja fazer.
Will Eddins
O problema no meu caso é que eu já uso um conversor aqui que faz outra coisa. Eu postei uma resposta, por favor, dê uma olhada.
Shimmy Weitzhandler
pode querer usar IsNullOrWhiteSpace () para permitir que "" seja contado como nulo (provavelmente o que você deseja)
Simon_Weaver
+1 No entanto: o preço é sua fonte aqui, mas você está correto. TargetNullValue não é apropriado aqui - TargetNullValue define o destino quando a fonte é nula - enquanto queremos definir a fonte (como nulo) quando o destino é um determinado valor (um vazio string) - que o seu conversor faz.
markmnl
5

Você pode tentar usar um ValueConverter (IValueConverter) http://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx

Da parte de trás da minha cabeça aqui, algo como:

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);
    }
}

(Pode ser necessário alguns ajustes)

TimothyP
fonte
Eu preferiria uma forma Xamly, mas não consigo pensar em nada
Shimmy Weitzhandler