Home > Mobile >  How to prevent MultiBinding chain through null object
How to prevent MultiBinding chain through null object

Time:05-18

I have the following XAML code:

        <TextBox Text="Image.Bytes" IsReadOnly="True"/>
        <TextBox IsReadOnly="True">
             <TextBox.Text>
                <MultiBinding Converter="{StaticResource ConcatTextConverter}" ConverterParameter="x">
                    <Binding Path="Image.Width"/>
                    <Binding Path="Image.Height"/>
                </MultiBinding>
            </TextBox.Text>
        </TextBox>
        

The ConcatTextConverter is a simple converter doing as follows:

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        string result = string.Empty;
        string separator = parameter?.ToString() ?? "";

        if(values?.Any() == true)
        {
            result = string.Join(separator, values);
        }

        return result;
    }

The Problem happens, when property "Image" is null. The first textbox just shows nothing as whished.

The second, however, shows "DependencyProperty.UnsetValue}x{DependencyProperty.UnsetValue}"

The values given into the converter are of type: values[0].GetType() {Name = "NamedObject" FullName = "MS.Internal.NamedObject"} System.Type {System.RuntimeType} Unfortunately I can't acces to this type MS.Internal.NamedObject to filter it in the converter in case of happening.

Now the Question is: What is the best way to prevent calling the converter in first place, when some object in the binding chain is null? - Or secondly: what would be the best approach to identify such "values" in the converter?

CodePudding user response:

You can't avoid that the converter is called, but you can check whether all of the Bindings did produce a value.

public object Convert(
    object[] values, Type targetType, object parameter, CultureInfo culture)
{
    string result = string.Empty;
    string separator = parameter?.ToString() ?? "";

    if (values.All(value => value != DependencyProperty.UnsetValue))
    {
        result = string.Join(separator, values);
    }

    return result;
}

CodePudding user response:

You do not need a converter to concatenate strings. All you need is a StringFormat attribute on your MultiBinding.

Also, you do not need a TextBox. Since you've set it to IsReadOnly="true", a TextBlock would do the same thing

This binding will give you an empty string when there is no image

<TextBlock> 
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0}x{1}">
            <Binding Path="Image.Width"/>
            <Binding Path="Image.Height"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

If you instead would want a string like, say, "0x0" when there is no image, you could use "FallbackValue` attributes on the individual bindings to make that happen.

 <TextBlock> 
    <TextBlock.Text>
        <MultiBinding StringFormat="{}{0}x{1}">
            <Binding Path="Image.Width"   FallbackValue="0"/>
            <Binding Path="Image.Height"  FallbackValue="0"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Edited to add: The FallbackValue approach also works with Clemens excellent answer. And his suggestion to make your converter more robust is a good thing to do regardless of which approach you use.

  • Related