Условное текстовое связывание XAML

У меня есть 3 свойства, которые я пытаюсь связать с Textblock в XAML. Один из них является условным, а два других являются строками, которые я хочу отображать в зависимости от этого условного.

<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}}"/>

Это работает, но теперь текстовые блоки должны иметь разные имена. Могу ли я превратить это в один TextBlock с условным внутри него?

Ответ 1

Вы можете добиться этого с помощью стиля и 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>

Альтернативой может быть использование MultiBinding с конвертером с несколькими значениями:

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

Конвертер будет выглядеть так:

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

Ответ 2

Да, вы можете просто обернуть их в TextBlock следующим образом:

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

Однако, я думаю, лучший ответ - тот, который дал Клеменс (используя DataTrigger).

Ответ 3

На мой взгляд, лучшим решением этой проблемы было бы новое строковое свойство в вашей модели представления, которое возвращает либо TrueText либо FalseText зависимости от условия. С таким свойством вы можете просто использовать простую привязку.

public string TheNewProperty
{
    get
    {
        return ShowTrueText ? TrueText : FalseText;
    }
}
<TextBlock Text="{Binding TheNewProperty}" Style="{StaticResource styleSimpleText}"/>

Ответ 4

То, как мы делаем этот тип вещей для MVVM, - это создать свойство в вашей модели просмотра для этого. Это позволяет вам провести единичное тестирование для вашего состояния на viewmodel.

Свойство в вашей модели просмотра будет строковым значением, к которому привязан TextBlock. В какой-то точке viewmodel определит значение этой строки на основе требуемой условной логики.

Ответ 5

Вы можете настроить его в своей модели просмотра и определить, какой текст будет отображаться.

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

Затем вы привязываетесь к нему только одним текстовым блоком. Не требуется конвертер видимости.
Если есть состояние, в котором текст не должен отображаться, вы также можете это сделать.

<TextBlock Text="{Binding ResultText}" Style="{StaticResource styleSimpleText}" />