55

Is there a standard way to set a default or fallback value for a WPF binding if the bound string is empty?

<TextBlock Text="{Binding Name, FallbackValue='Unnamed'" />

The FallbackValue only seems to kick in when Name is null, but not when it is set to String.Empty.

2

4 Answers 4

85

DataTrigger is the way i do it like this:

<TextBox>
  <TextBox.Style>
        <Style TargetType="{x:Type TextBox}"  BasedOn="{StaticResource ReadOnlyTextBox}">
            <Setter Property="Text" Value="{Binding Name}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=Name.Length, FallbackValue=0, TargetNullValue=0}" Value="0">
                    <Setter Property="Text" Value="{x:Static local:ApplicationLabels.NoValueMessage}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>
Sign up to request clarification or add additional context in comments.

4 Comments

I like this approach because it let's me bind the default value to another property in my ViewModel. Thanks :)
you can probably also do Name and empty string instead of Name.length, totally love this approach :)
Seeing as Name is generally a string, then Name.Length would be of type Int32. For this reason, there is no need specify TargetNullValue because the the expression will never evaluate to null, granted it evaluates at all. FallbackValue is the property pulling the weight here.
ugly way to do this... should be 1 liner for such a simple thing.
45

I was under the impression that FallbackValue provides a value when the binding fails and TargetNullValue provides a value when the bound value is null.

To do what you want you will either need a converter (possibly with a parameter) to convert an empty string to a target value, or put the logic in your view model.

I would probably go with a converter something like this (not tested).

public class EmptyStringConverter : MarkupExtension, IValueConverter
{  
    public object Convert(object value, Type targetType, 
                          object parameter, CultureInfo culture)
    {
        return string.IsNullOrEmpty(value as string) ? parameter : value;
    }

    public object ConvertBack(object value, Type targetType, 
                              object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
}

Comments

11

You should create a converter for this, which implements IValueConverter

public class StringEmptyConverter : IValueConverter {

public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      return string.IsNullOrEmpty((string)value) ? parameter : value;
    }

public object ConvertBack(
      object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
      throw new NotSupportedException();
    }

}

Then in xaml you'd just provide the converter to the binding, (xxx just represents your Window / UserControl / Style ... where the binding is)

<xxx.Resources>
<local:StringEmptyConverter x:Key="StringEmptyConverter" />
</xxx.Resources>
<TextBlock Text="{Binding Name, Converter={StaticResource StringEmptyConverter}, ConverterParameter='Placeholder Text'}" />

3 Comments

I need to specify a different default string for every binding, but I could pass in the string as the ConverterParameter.
@Viv Why binding to Name property, not to Text?
@Andrzej huh Name is the property the OP had mentioned in his question.
0

You could use a converter and do the respective validation on it.

Binding="{Binding Path=Name, Converter={StaticResource nameToOtherNameConverter}}"

and in your converter

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (!string.IsNullOrEmpty(value.ToString()))
        { /*do something and return your new value*/ }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.