Wie binde ich mehrere Werte an einen einzelnen WPF TextBlock?

210

Ich verwende derzeit TextBlockFolgendes, um den Wert einer Eigenschaft mit dem Namen zu binden Name:

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

Jetzt möchte ich eine andere Eigenschaft IDmit demselben Namen binden TextBlock.

Ist es möglich, zwei oder mehr Werte an denselben zu binden TextBlock? Kann es mit einfacher Verkettung gemacht werden, wie Name + IDund wenn nicht, wie könnte dies sonst angegangen werden?

Verbringen
quelle

Antworten:

434

Sie können eine MultiBindingmit der StringFormatEigenschaft kombinierte verwenden . Die Verwendung würde wie folgt aussehen:

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

Wenn Sie Nameeinen Wert von Foound IDeinen Wert von 1angeben, ist Ihre Ausgabe im TextBlock dann Foo + 1.

Note: dass dies nur in .NET 3.5 SP1 und 3.0 SP2 oder höher unterstützt wird.

Richard McGuire
quelle
5
@Preet - Ich bin mir nicht sicher, ob das '{}' in diesem Fall erforderlich ist. Ich habe es eingefügt, da es für das MSDN-Beispiel verwendet wurde. Im Allgemeinen wird es jedoch als Escape-Sequenz für den XAML-Parser benötigt, um Verwechslungen mit der Binding-Markup-Erweiterung zu vermeiden.
Richard McGuire
2
Dies hat einen Nebeneffekt. Wenn Sie diese Methode in so etwas wie einem DataGridSortierverhalten verwenden, funktioniert dies leider nicht. Eine geeignetere Lösung wäre, eine schreibgeschützte Eigenschaft in Ihrem Modell mit dem entsprechenden Zeichenfolgenformat zum Binden zu erstellen. Unnötig zu erwähnen, dass dies eine gute Möglichkeit ist, schnell zu formatieren, wenn auch etwas ausführlich.
Brett Ryan
34
Sie benötigen nur {}, wenn die Formatzeichenfolge mit dem Parameter {0} beginnt. Sie wird nicht benötigt, wenn die Formatzeichenfolge mit einem Text beginnt. Beispiel: "{} {0} + {1}" "Seite {0} von {1}"
Dakianth
Es funktionierte nicht in einem WPF-Projekt .Net 4.0 Visual Studio 2017.
Sorush
@ Patricks Lösung hat bei mir funktioniert. Ich konnte das nicht zum Laufen bringen. Ich hatte diesen FehlerXamlParseException: 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

Ich weiß, dass dies viel zu spät ist, aber ich dachte, ich würde noch einen weiteren Weg hinzufügen, dies zu tun.

Sie können die Tatsache nutzen, dass die Text-Eigenschaft mit " Run s" festgelegt werden kann, sodass Sie für jeden Lauf mehrere Bindungen mit einem Run einrichten können. Dies ist nützlich, wenn Sie keinen Zugriff auf MultiBinding haben (was ich bei der Entwicklung für Windows Phone nicht gefunden habe).

<TextBlock>
  <Run Text="Name = "/>
  <Run Text="{Binding Name}"/>
  <Run Text=", Id ="/>
  <Run Text="{Binding Id}"/>
</TextBlock>
Patrick
quelle
4
Dies ist ein sehr praktischer Ansatz, wenn Sie an mehrere Zeichenfolgen binden, die als DynamicResource verwendet werden, da Sie dafür keine MultiBinding mit StringFormat verwenden können.
Slugster
Ich habe es gerade versucht. Es funktioniert, aber jedes Element (sogar die Geometrie), das (bei einer Aktualisierung) gezeichnet wird, blinkt jetzt aus irgendeinem Grund bei jedem Häkchen. Ich werde die andere Methode ausprobieren.
Logan Klenner
6
Dies kann schwierig werden, wenn der Text lokalisiert werden muss, da die Reihenfolge fest codiert ist.
BlueM
1
Eine andere Verwendung dieses Ansatzes ist das Anwenden eines anderen Stils für jede Bindung
Hamid Naeemi
beste Antwort für 2019
Fábio BC Souza
23

Wenn es sich nur um Textblöcke (und damit um eine Einwegbindung) handelt und Sie nur Werte verketten möchten, binden Sie einfach zwei Textblöcke und legen Sie sie in ein horizontales Stapelfenster.

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

Dadurch wird der Text angezeigt (was bei allen Textblöcken der Fall ist), ohne dass weitere Codierungen erforderlich sind. Sie können einen kleinen Rand darauf setzen, damit sie richtig aussehen.

CodeWarrior
quelle
11

Verwenden Sie einen 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;
    }
}

und im Markup

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

. . .

<TextBlock Text="{Binding Name, Converter={StaticResource MyConverter Parameter=ID}}" />
Preet Sangha
quelle
Ja, dies wurde vor 6 Jahren geschrieben, und Sie binden den "Namen" als erstes Argument an den Konverter (im Code als Wert bezeichnet) und die ID (eine Zeichenfolge aus der Frage) als zweites Argument.
Preet Sangha