views:

863

answers:

3

The TextWrapping property of the TextBox has three possible values:

  • Wrap
  • NoWrap
  • WrapWithOverflow

I would like to bind to the IsChecked property of a MenuItem. If the MenuItem is checked, I want to set the TextWrapping property of a TextBox to Wrap. If the MenuItem is not checked, I want to set the TextWrapping property of the TextBox to NoWrap.

To sum up, I am trying to bind a control that has two states to two values of an enumeration that has more than two values.

[edit] I would like to accomplish this in XAML, if possible.

[edit] I figured out how to do this using an IValueConverter. Perhaps there is a better way to do this? Here is what I did:


In Window.Resources, I declared a reference to my ValueConverter.

<local:Boolean2TextWrapping x:Key="Boolean2TextWrapping" />

In my TextBox, I created the binding to a MenuItem and included the Converter in the binding statement.

TextWrapping="{Binding ElementName=MenuItemWordWrap, Path=IsChecked, Converter={StaticResource Boolean2TextWrapping}}"

and the ValueConverter looks like this:

public class Boolean2TextWrapping : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo cultureInfo)
        {
            if (((bool)value) == false)
            {
                return TextWrapping.NoWrap;
            }
            return TextWrapping.Wrap;
        }

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

I assume you are talking about .NET. I don't think databinding will work here because the values are not of the same type (boolean vs enum). The easiest solution would be to handle the CheckedChanged event of that menu item and adjust the wrap mode of the textbox accordingly.

NYSystemsAnalyst
Wrong. It can be done in xaml.
Will
A: 

I think that the only and right the typical way to do this is to use a value converter like you already have done.

Sometimes you can find an existing value converter that you have built already ... or even better that Microsoft has built for you. For example, in System.Windows.Controls, Microsoft has written a BooleanToVisibilityConverter ... which converts a bool into a Visibility enum ... converting True to Visible and False to Collapsed (and not worrying about Hidden).

One idea is to use .NET Reflector, navigate to the System.Windows.Data.IValueConverter, and then use the Analyze feature (in particular, 'Used by') and see what things have implemented IValueConverter ... and you just might get lucky to find a converter that suits your purpose.

On a related note, BooleanToVisibilityConverter is very similar to what you are trying to do above.

Edit: I really like Todd White's suggestion of styling the TextBox and using a DataTrigger in the Style. It is a very good idea if you want to avoid a Converter.

cplotts
+2  A: 

If you want to do this all in xaml you need to use a Style and a DataTrigger.

<StackPanel>
    <CheckBox x:Name="WordWrap">Word Wrap</CheckBox>
    <TextBlock Width="50">
        Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Proin lacinia nibh non augue. Pellentesque pretium neque et neque auctor adipiscing.

        <TextBlock.Style>
            <Style TargetType="{x:Type TextBlock}">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsChecked, ElementName=WordWrap}" Value="True">
                        <Setter Property="TextWrapping" Value="Wrap" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
</StackPanel>
Todd White
How does the TextBox know to switch to NoWrap when IsChecked is False? It works -- but I don't understand why. Is it because TextWrapping on a TextBox has a default or something else?
Timothy Lee Russell
Yes, when a trigger is no longer being used then it falls back to the default value.
Todd White
How do you determine what the default value is for a given property of an object, besides experimentation in the debugger?In other words, how would I know not to make the DataTrigger, "IsChecked = false" and the Setter, "TextWrapping = NoWrap" assuming that it would fall back to "Wrap"?Thanks!
Timothy Lee Russell
This is where the MSDN Documentation comes in. In the case of TextBlock.TextWrapping I looked it up here http://msdn.microsoft.com/en-us/library/system.windows.controls.textblock.textwrapping.aspx. On that page it says 'The default is TextWrapping.NoWrap'
Todd White
I like it. I always try to avoid using a converter if possible. I have never used a DataTrigger like this before. Useful trick.
cplotts