简体   繁体   中英

Visibility of two controls via data binding and value converter

I have two controls contained within a data template. Control #1 is a TextBlock known as "TXTBLOCK". Control #2 is a TextBox known as "TXTBOX":

TXTBLOCK has Visibility set to TextBox Visibility using the converter to give the opposite value.

Example:

<TextBlock Name="TXTBLOCK" Visibility="{Binding ElementName=**TXTBOX**, Path=Visibility, Converter={StaticResource toggleVisConverter}}" />

<TextBox Name="TXTBOX" Visibility="{Binding ElementName=**TXTBLOCK**, Path=Visibility, Converter={StaticResource toggleVisConverter}}" />

Converter is:

        if (targetType == typeof(Visibility))
        {
            Visibility vis = (Visibility)value;
            if (vis == Visibility.Collapsed)
            {
                return Visibility.Visible;
            }
            else
            {
                return Visibility.Collapsed;
            }
            //var vis == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
        }

        //return vis;
        throw new InvalidOperationException("Value must be of type 'Visibility'.");

Now...to me this should be simple. Changing the visibility of one will set the other's visibility to false.

Not the case...

Works the very first time through and then the converter stops being called.

Even if I explicitly state: "TXTBOX.Visibility = Visibility.Hidden" in code behind, the converter never gets called.

What gives? What am I missing?

This is my first post on SO...so forgive me if I missed something or need to provide more info. I'll be happy to do it

Thanks!

It seems WPF has ways of detecting and avoiding stack overflows in data-binding. I'm aware of one , and it seems you've found another.

When you change the visibility of one of your controls, something like the following happens (in theory, at least):

  • You change the visibility of the TextBlock (say),
  • This causes a change in the visibility of the TextBox,
  • This then causes another change in the visibility of the TextBlock,
  • This causes another change in the visibility of the TextBlock, using the first binding again,
  • ...

This would go on forever and quite probably cause a stack overflow, if it weren't for WPF detecting situations such as this automatically. In this case it seems that it stops listening to the bindings you've created once it detects it could be heading towards a stack overflow.

I haven't run your code, but I suspect that WPF doesn't inform you about this either. I'm guessing there's no exceptions, warnings, nor even a debugging line written to the Output window.

It seems the pair of bindings is the problem here. What I recommend you do is:

  • Make your ValueConverter a two-way converter, by implementing the ConvertBack method. (If all your converter is doing is swapping between Collapsed and Visible , ConvertBack can probably just call Convert .)
  • Make one of the bindings (it doesn't matter which one) two-way by adding Mode=TwoWay , and remove the other binding. A TwoWay binding will be enough for communication in both directions between your two controls.

EDIT : my comment about ConvertBack was that you could implement it as follows:

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    return Convert(value, targetType, parameter, culture);
}

This is because all your converter is doing is swapping between Visible and Collapsed , and converting one way is the same as converting back. This comment was essentially an aside; you can of course implement ConvertBack as you wish, but you will need to implement ConvertBack if you are using your converter in a TwoWay binding.

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