Условное текстовое связывание 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}" />