Jak powiązać wiele wartości z jednym TextBlock WPF?

210

Obecnie używam TextBlockponiżej, aby powiązać wartość właściwości o nazwie Name:

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

Teraz chcę powiązać inną właściwość o IDtej samej nazwie TextBlock.

Czy można powiązać dwie lub więcej wartości z tym samym TextBlock? Czy można tego dokonać za pomocą prostej konkatenacji, na przykład, Name + IDa jeśli nie, to jak inaczej można do tego podejść?

Wydać
źródło

Odpowiedzi:

434

Możesz użyć w MultiBindingpołączeniu z StringFormatwłaściwością. Użycie byłoby podobne do następującego:

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

Podanie Namewartości Fooi IDwartości 1wyjściowej w TextBlock byłoby wtedy Foo + 1.

Note: że jest to obsługiwane tylko w .NET 3.5 SP1 i 3.0 SP2 lub nowszym.

Richard McGuire
źródło
5
@Preet - tak naprawdę nie jestem pewien, czy „{}” jest konieczne w tym przypadku, dołączyłem go, ponieważ został użyty w próbce MSDN. Zasadniczo jednak jest potrzebna jako sekwencja ucieczki dla parsera XAML, aby uniknąć pomyłki z rozszerzeniem znacznika Binding.
Richard McGuire,
2
Jest na to jeden efekt uboczny. Jeśli użyjesz tej metody do czegoś w rodzaju DataGridsortowania, niestety nie zadziała. Bardziej odpowiednim rozwiązaniem byłoby utworzenie właściwości tylko do odczytu w modelu z odpowiednim formatem ciągu, z którym można się wiązać. Nie trzeba dodawać, że jest to dobry sposób na szybkie sformatowanie, choć trochę zbyt szczegółowe.
Brett Ryan,
34
potrzebujesz tylko {}, gdy ciąg formatu zaczyna się od parametru {0}, nie jest potrzebny, jeśli ciąg formatu zaczyna się od tekstu. np .: „{} {0} + {1}” „Strona {0} z {1}”
Dakianth,
Nie działał w projekcie WPF .Net 4.0 Visual Studio 2017.
Sorush
@ Rozwiązanie Patrick działało dla mnie. Nie mogłem tego uruchomić. Miałem ten błądXamlParseException: 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

Wiem, że jest już późno, ale pomyślałem, że dodam jeszcze jeden sposób.

Możesz skorzystać z faktu, że właściwość Text można ustawić za pomocą „ Run s”, dzięki czemu możesz skonfigurować wiele powiązań za pomocą Run dla każdego z nich. Jest to przydatne, jeśli nie masz dostępu do MultiBinding (którego nie znalazłem podczas programowania dla Windows Phone)

<TextBlock>
  <Run Text="Name = "/>
  <Run Text="{Binding Name}"/>
  <Run Text=", Id ="/>
  <Run Text="{Binding Id}"/>
</TextBlock>
Patrick
źródło
4
Jest to bardzo przydatne podejście do łączenia z kilkoma łańcuchami, które są pozyskiwane jako DynamicResource, ponieważ nie można do tego użyć MultiBinding z StringFormat.
slugster,
Właśnie tego spróbowałem. Działa, jednak każdy element (nawet geometria), który zostanie narysowany (podczas odświeżania), teraz z jakiegoś powodu miga przy każdym tiku. Idę wypróbować inną metodę.
Logan Klenner,
6
Może to być trudne, jeśli tekst musi być zlokalizowany, ponieważ kolejność jest zakodowana na stałe.
BlueM
1
Innym zastosowaniem tego podejścia jest zastosowanie innego stylu dla każdego wiązania
Hamid Naeemi
najlepsza odpowiedź na 2019 r.
Fábio BC Souza
23

Jeśli będą to tylko bloki tekstowe (a zatem wiązanie jednokierunkowe), a chcesz po prostu połączyć wartości, po prostu powiąż dwa bloki tekstowe i umieść je w poziomym panelu stosu.

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

Spowoduje to wyświetlenie tekstu (tak jak robią to wszystkie bloki Textblocks) bez konieczności dalszego kodowania. Możesz jednak nałożyć na nie niewielki margines, aby wyglądały dobrze.

CodeWarrior
źródło
11

Użyj 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;
    }
}

i w znacznikach

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

. . .

<TextBlock Text="{Binding Name, Converter={StaticResource MyConverter Parameter=ID}}" />
Preet Sangha
źródło
Tak - zostało to napisane 6 lat temu, a „Konwerter” wiąże się jako pierwszy argument z konwerterem (zwany wartością w kodzie), a identyfikator (ciąg z pytania) jako drugi argument.
Preet Sangha