简体   繁体   中英

How to prevent MultiBinding chain through null object

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?

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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM