Comment lier plusieurs valeurs à un seul WPF TextBlock?

210

J'utilise actuellement ce qui TextBlocksuit pour lier la valeur d'une propriété nommée Name:

<TextBlock Text="{Binding Name}" />

Maintenant, je veux lier une autre propriété portant IDle même nom TextBlock.

Est-il possible de lier deux ou plusieurs valeurs à la même chose TextBlock? Peut-on le faire avec une simple concaténation, comme Name + IDet sinon, comment pourrait-on aborder cela?

Dépenser
la source

Réponses:

434

Vous pouvez utiliser un MultiBindingcombiné avec la StringFormatpropriété. L'utilisation ressemblerait à ce qui suit:

<TextBlock>
    <TextBlock.Text>    
        <MultiBinding StringFormat="{}{0} + {1}">
            <Binding Path="Name" />
            <Binding Path="ID" />
        </MultiBinding>
    </TextBlock.Text>
</TextBlock>

Donner Nameune valeur de Fooet IDune valeur de 1, votre sortie dans le TextBlock serait alors Foo + 1.

Note: que cela n'est pris en charge que dans .NET 3.5 SP1 et 3.0 SP2 ou version ultérieure.

Richard McGuire
la source
5
@Preet - Je ne sais pas vraiment si le '{}' est nécessaire dans ce cas, je l'ai inclus car il a été utilisé sur l'échantillon MSDN. Cependant, en général, il est nécessaire en tant que séquence d'échappement pour l'analyseur XAML afin d'éviter toute confusion avec l'extension de balisage de liaison.
Richard McGuire
2
Il y a un effet secondaire à cela. Si vous utilisez cette méthode dans quelque chose comme un DataGridcomportement de tri, cela ne fonctionne malheureusement pas. Une solution plus appropriée serait de créer une propriété en lecture seule dans votre modèle avec le format de chaîne approprié pour la liaison. Inutile de dire que c'est une bonne façon de formater rapidement, quoique un peu verbeux.
Brett Ryan
34
vous avez juste besoin de {} lorsque la chaîne de format commence par le paramètre {0}, elle n'est pas nécessaire si la chaîne de format commence par un texte. ex: "{} {0} + {1}" "Page {0} de {1}"
Dakianth
Cela n'a pas fonctionné sur un projet WPF .Net 4.0 Visual Studio 2017.
Sorush
@ La solution de Patrick a fonctionné pour moi. Je n'ai pas pu faire fonctionner ça. J'ai eu cette erreurXamlParseException: A 'Binding' cannot be set on the 'Path' property of type 'Binding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.
Tyson Williams
127

Je sais que c'est un peu tard, mais j'ai pensé ajouter encore une autre façon de procéder.

Vous pouvez tirer parti du fait que la propriété Text peut être définie à l'aide de " Exécuter s", vous pouvez donc configurer plusieurs liaisons en utilisant une Exécuter pour chacune. Ceci est utile si vous n'avez pas accès à MultiBinding (que je n'ai pas trouvé lors du développement pour Windows Phone)

<TextBlock>
  <Run Text="Name = "/>
  <Run Text="{Binding Name}"/>
  <Run Text=", Id ="/>
  <Run Text="{Binding Id}"/>
</TextBlock>
Patrick
la source
4
Il s'agit d'une approche très pratique à utiliser lors de la liaison à plusieurs chaînes provenant d'un DynamicResource car vous ne pouvez pas utiliser un MultiBinding avec StringFormat pour cela.
slugster
Je viens d'essayer ça. Cela fonctionne, mais chaque élément (même la géométrie) qui est dessiné (lors d'un rafraîchissement) clignote désormais à chaque tick pour une raison quelconque. Je vais essayer l'autre méthode.
Logan Klenner
6
Cela peut devenir difficile si le texte doit être localisé car la commande est codée en dur.
BlueM
1
Une autre utilisation de cette approche consiste à appliquer un style différent pour chaque liaison
Hamid Naeemi
meilleure réponse pour 2019
Fábio BC Souza
23

Si ce ne sont que des blocs de texte (et donc une liaison à sens unique) et que vous souhaitez simplement concaténer des valeurs, liez simplement deux blocs de texte et placez-les dans un panneau de pile horizontal.

    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}"/>
        <TextBlock Text="{Binding ID}"/>
    </StackPanel>

Cela affichera le texte (ce que font tous les blocs de texte) sans avoir à faire de codage supplémentaire. Vous pouvez cependant leur donner une petite marge pour les faire bien paraître.

CodeWarrior
la source
11

Utilisez un ValueConverter

[ValueConversion(typeof(string), typeof(String))]
public class MyConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return string.Format("{0}:{1}", (string) value, (string) parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {

        return DependencyProperty.UnsetValue;
    }
}

et dans le balisage

<src:MyConverter x:Key="MyConverter"/>

. . .

<TextBlock Text="{Binding Name, Converter={StaticResource MyConverter Parameter=ID}}" />
Preet Sangha
la source
Oui - cela a été écrit il y a 6 ans, et vous liez le "Nom" comme premier argument au convertisseur (appelé valeur dans le code), et l'ID (une chaîne de la question) comme deuxième argument.
Preet Sangha