Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional text binding XAML

Tags:

c#

wpf

xaml

I have 3 properties that I'm trying to bind to a Textblock in XAML. One is a conditional and the other two are the strings that I want to display depending on that conditional.

<TextBlock Text="{Binding TrueText}" Style="{StaticResource styleSimpleText}" Visibility="{Binding ShowTrueText, Converter={StaticResource boolToVisibilityConverter}}"/>
<TextBlock Text="{Binding FalseText}" Style="{StaticResource styleSimpleText}" Visibility="{Binding ShowTrueText, Converter={StaticResource invertedBoolToVisibilityConverter}}"/>

This works, but now the textblocks have to have different names. Can I turn this into one TextBlock with the conditional inside of it?

like image 982
Stacked Avatar asked Mar 02 '15 18:03

Stacked


4 Answers

You could achieve that with a Style and a DataTrigger:

<TextBlock>
    <TextBlock.Style>
        <Style TargetType="TextBlock">
            <Setter Property="Text" Value="{Binding FalseText}"/>
            <Style.Triggers>
                <DataTrigger Binding="{Binding ShowTrueText}" Value="True">
                    <Setter Property="Text" Value="{Binding TrueText}"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBlock.Style>
</TextBlock>

An alternative would be to use a MultiBinding with a multi-value converter:

<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource TextConverter}">
            <Binding Path="TrueText"/>
            <Binding Path="FalseText"/>
            <Binding Path="ShowTrueText"/>
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

The converter would look like this:

public class TextConverter : IMultiValueConverter
{
    public object Convert(
        object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var trueText = (string)values[0];
        var falseText = (string)values[1];
        var showTrueText = (bool)values[2];
        return showTrueText ? trueText : falseText;
    }

    public object[] ConvertBack(
        object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}
like image 67
Clemens Avatar answered Oct 23 '22 22:10

Clemens


You could set it up in your viewmodel and let it determine which text to show.

private static readonly string TRUETEXT = "This is the text to show when true";
    private static readonly string FALSETEXT = "This is the text to show when false";

    private bool _myBooleanProperty;
    public bool MyBooleanProperty
    {
        get { return _myBooleanProperty; }
        set
        {
            if (_myBooleanProperty != value)
            {
                _myBooleanProperty = value;
                OnPropertyChanged("MyBooleanProperty");
                OnPropertyChanged("ResultText");
            }
        }
    }

    public string ResultText
    {
        get
        {
            return MyBooleanProperty ? TRUETEXT : FALSETEXT;
        }
    }

Then you bind to it with just a single textblock. No visibility converter needed.
If there is a state where no text should show, you could work that in as well.

<TextBlock Text="{Binding ResultText}" Style="{StaticResource styleSimpleText}" />
like image 37
Mark W Avatar answered Sep 29 '22 15:09

Mark W


The way we do this type of thing for MVVM is to create a property in your viewmodel for this. This allows for you to have unit testing for your condition on the viewmodel.

The property in your viewmodel will be the string value that the TextBlock is bound to. The viewmodel at some point will determine the value of that string based on the conditional logic that you need.

like image 1
ujjb Avatar answered Oct 23 '22 22:10

ujjb


Yes, you can, just wrap them in a TextBlock as follows:

<TextBlock x:name="myTextBlock" Style="{StaticResource styleSimpleText}">
    <TextBlock Text="{Binding TrueText}" Visibility="{Binding ShowTrueText, Converter={StaticResource boolToVisibilityConverter}}"/>
    <TextBlock Text="{Binding FalseText}" Visibility="{Binding ShowTrueText, Converter={StaticResource invertedBoolToVisibilityConverter}}"/>
</TextBlock>

However, I think the best answer is the one provided by Clemens (using a DataTrigger).

like image 1
theartwebreathe Avatar answered Oct 23 '22 23:10

theartwebreathe