web-dev-qa-db-fra.com

Liaison de texte conditionnelle XAML

J'ai 3 propriétés que j'essaie de lier à un Textblock en XAML. L'une est une condition et les deux autres sont les chaînes que je veux afficher en fonction de cette condition.

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

Cela fonctionne, mais les blocs de texte doivent maintenant avoir des noms différents. Puis-je transformer cela en un TextBlock avec le conditionnel à l'intérieur?

13
Stacked

Vous pouvez y parvenir avec un style et un 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>

Une alternative consisterait à utiliser une liaison multiple avec un convertisseur à valeurs multiples:

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

Le convertisseur ressemblerait à ceci:

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

Pour MVVM, nous procédons de la sorte pour créer une propriété dans votre modèle de vue. Cela vous permet d’avoir des tests unitaires de votre condition sur le modèle de vue. 

La propriété dans votre viewmodel sera la valeur de chaîne à laquelle le TextBlock est lié. Le modèle de vue déterminera à un moment donné la valeur de cette chaîne en fonction de la logique conditionnelle dont vous avez besoin.

1
ujjb

À mon avis, la meilleure solution à ce problème serait une nouvelle propriété de chaîne dans votre viewmodel qui renvoie TrueText ou FalseText en fonction du conditionnel. Avec une telle propriété, vous pouvez simplement utiliser une liaison simple.

public string TheNewProperty
{
  get
  {
    return ShowTrueText ? TrueText : FalseText;
  }
}

<TextBlock Text="{Binding TheNewProperty}" Style="{StaticResource styleSimpleText}"/>
1
Thomas F.

Oui, vous pouvez simplement les envelopper dans un TextBlock comme suit:

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

Cependant, je pense que la meilleure réponse est celle fournie par Clemens (en utilisant un DataTrigger).

1
theartwebreathe

Vous pouvez le configurer dans votre modèle de vue et le laisser déterminer le texte à afficher.

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

Ensuite, vous vous y attachez avec un seul bloc de texte. Aucun convertisseur de visibilité nécessaire.
S'il y a un état dans lequel aucun texte ne doit apparaître, vous pouvez également l'inclure.

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